1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
5 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
30 #include "pcodeflow.h"
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
37 #define STRCASECMP strcasecmp
40 /****************************************************************/
41 /****************************************************************/
43 static peepCommand peepCommands[] = {
45 {NOTBITSKIP, "_NOTBITSKIP_"},
46 {BITSKIP, "_BITSKIP_"},
47 {INVERTBITSKIP, "_INVERTBITSKIP_"},
54 // Eventually this will go into device dependent files:
55 pCodeOpReg pic16_pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
56 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
71 static hTab *pic16MnemonicsHash = NULL;
72 static hTab *pic16pCodePeepCommandsHash = NULL;
76 static pFile *the_pFile = NULL;
77 static pBlock *pb_dead_pcodes = NULL;
79 /* Hardcoded flags to change the behavior of the PIC port */
80 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
81 static int functionInlining = 1; /* inline functions if nonzero */
82 int pic16_debug_verbose = 1; /* Set true to inundate .asm file */
84 //static int GpCodeSequenceNumber = 1;
85 static int GpcFlowSeq = 1;
87 extern void pic16_RemoveUnusedRegisters(void);
88 extern void pic16_RegsUnMapLiveRanges(void);
89 extern void pic16_BuildFlowTree(pBlock *pb);
90 extern void pic16_pCodeRegOptimizeRegUsage(int level);
91 extern int pic16_picIsInitialized(void);
94 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
95 extern int mnem2key(char const *mnem);
96 #endif // OPT_DISABLE_PIC
98 /****************************************************************/
99 /* Forward declarations */
100 /****************************************************************/
102 void pic16_unlinkpCode(pCode *pc);
104 static void genericAnalyze(pCode *pc);
105 static void AnalyzeGOTO(pCode *pc);
106 static void AnalyzeSKIP(pCode *pc);
107 static void AnalyzeRETURN(pCode *pc);
110 static void genericDestruct(pCode *pc);
111 static void genericPrint(FILE *of,pCode *pc);
113 static void pCodePrintLabel(FILE *of, pCode *pc);
114 static void pCodePrintFunction(FILE *of, pCode *pc);
115 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
116 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
117 char *pic16_get_op( pCodeOp *pcop,char *buff,size_t buf_size);
118 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
119 int pic16_pCodePeepMatchRule(pCode *pc);
120 static void pBlockStats(FILE *of, pBlock *pb);
121 static pBlock *newpBlock(void);
122 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
123 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
124 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
125 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
128 /****************************************************************/
129 /* PIC Instructions */
130 /****************************************************************/
132 pCodeInstruction pic16_pciADDWF = {
133 {PC_OPCODE, NULL, NULL, 0, NULL,
146 1,0, // dest, bit instruction
148 0, // literal operand
150 0, // fast call/return mode select bit
152 (PCC_W | PCC_REGISTER), // inCond
153 (PCC_REGISTER | PCC_Z) // outCond
156 pCodeInstruction pic16_pciADDFW = {
157 {PC_OPCODE, NULL, NULL, 0, NULL,
170 0,0, // dest, bit instruction
172 0, // literal operand
174 0, // fast call/return mode select bit
176 (PCC_W | PCC_REGISTER), // inCond
177 (PCC_W | PCC_Z) // outCond
180 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
181 {PC_OPCODE, NULL, NULL, 0, NULL,
194 1,0, // dest, bit instruction
196 0, // literal operand
198 0, // fast call/return mode select bit
200 (PCC_W | PCC_REGISTER | PCC_C), // inCond
201 (PCC_REGISTER | PCC_Z) // outCond
204 pCodeInstruction pic16_pciADDFWC = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
224 (PCC_W | PCC_REGISTER | PCC_C), // inCond
225 (PCC_W | PCC_Z) // outCond
228 pCodeInstruction pic16_pciADDLW = {
229 {PC_OPCODE, NULL, NULL, 0, NULL,
242 0,0, // dest, bit instruction
244 1, // literal operand
246 0, // fast call/return mode select bit
248 (PCC_W | PCC_LITERAL), // inCond
249 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
252 pCodeInstruction pic16_pciANDLW = {
253 {PC_OPCODE, NULL, NULL, 0, NULL,
266 0,0, // dest, bit instruction
268 1, // literal operand
270 0, // fast call/return mode select bit
272 (PCC_W | PCC_LITERAL), // inCond
273 (PCC_W | PCC_Z | PCC_N) // outCond
276 pCodeInstruction pic16_pciANDWF = {
277 {PC_OPCODE, NULL, NULL, 0, NULL,
290 1,0, // dest, bit instruction
292 0, // literal operand
294 0, // fast call/return mode select bit
296 (PCC_W | PCC_REGISTER), // inCond
297 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
300 pCodeInstruction pic16_pciANDFW = {
301 {PC_OPCODE, NULL, NULL, 0, NULL,
314 0,0, // dest, bit instruction
316 0, // literal operand
318 0, // fast call/return mode select bit
320 (PCC_W | PCC_REGISTER), // inCond
321 (PCC_W | PCC_Z) // outCond
324 pCodeInstruction pic16_pciBC = { // mdubuc - New
325 {PC_OPCODE, NULL, NULL, 0, NULL,
338 0,0, // dest, bit instruction
340 0, // literal operand
342 0, // fast call/return mode select bit
344 (PCC_REL_ADDR | PCC_C), // inCond
348 pCodeInstruction pic16_pciBCF = {
349 {PC_OPCODE, NULL, NULL, 0, NULL,
362 1,1, // dest, bit instruction
364 0, // literal operand
366 0, // fast call/return mode select bit
368 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
369 PCC_REGISTER // outCond
372 pCodeInstruction pic16_pciBN = { // mdubuc - New
373 {PC_OPCODE, NULL, NULL, 0, NULL,
386 0,0, // dest, bit instruction
388 0, // literal operand
390 0, // fast call/return mode select bit
392 (PCC_REL_ADDR | PCC_N), // inCond
396 pCodeInstruction pic16_pciBNC = { // mdubuc - New
397 {PC_OPCODE, NULL, NULL, 0, NULL,
410 0,0, // dest, bit instruction
412 0, // literal operand
414 0, // fast call/return mode select bit
416 (PCC_REL_ADDR | PCC_C), // inCond
420 pCodeInstruction pic16_pciBNN = { // mdubuc - New
421 {PC_OPCODE, NULL, NULL, 0, NULL,
434 0,0, // dest, bit instruction
436 0, // literal operand
438 0, // fast call/return mode select bit
440 (PCC_REL_ADDR | PCC_N), // inCond
444 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
445 {PC_OPCODE, NULL, NULL, 0, NULL,
458 0,0, // dest, bit instruction
460 0, // literal operand
462 0, // fast call/return mode select bit
464 (PCC_REL_ADDR | PCC_OV), // inCond
468 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
469 {PC_OPCODE, NULL, NULL, 0, NULL,
482 0,0, // dest, bit instruction
484 0, // literal operand
486 0, // fast call/return mode select bit
488 (PCC_REL_ADDR | PCC_Z), // inCond
492 pCodeInstruction pic16_pciBOV = { // mdubuc - New
493 {PC_OPCODE, NULL, NULL, 0, NULL,
506 0,0, // dest, bit instruction
508 0, // literal operand
510 0, // fast call/return mode select bit
512 (PCC_REL_ADDR | PCC_OV), // inCond
516 pCodeInstruction pic16_pciBRA = { // mdubuc - New
517 {PC_OPCODE, NULL, NULL, 0, NULL,
530 0,0, // dest, bit instruction
532 0, // literal operand
534 0, // fast call/return mode select bit
536 PCC_REL_ADDR, // inCond
540 pCodeInstruction pic16_pciBSF = {
541 {PC_OPCODE, NULL, NULL, 0, NULL,
554 1,1, // dest, bit instruction
556 0, // literal operand
558 0, // fast call/return mode select bit
560 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
561 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
564 pCodeInstruction pic16_pciBTFSC = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 0,1, // dest, bit instruction
580 0, // literal operand
582 0, // fast call/return mode select bit
584 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
585 PCC_EXAMINE_PCOP // outCond
588 pCodeInstruction pic16_pciBTFSS = {
589 {PC_OPCODE, NULL, NULL, 0, NULL,
602 0,1, // dest, bit instruction
604 0, // literal operand
606 0, // fast call/return mode select bit
608 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
609 PCC_EXAMINE_PCOP // outCond
612 pCodeInstruction pic16_pciBTG = { // mdubuc - New
613 {PC_OPCODE, NULL, NULL, 0, NULL,
626 0,1, // dest, bit instruction
628 0, // literal operand
630 0, // fast call/return mode select bit
632 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
633 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
636 pCodeInstruction pic16_pciBZ = { // mdubuc - New
637 {PC_OPCODE, NULL, NULL, 0, NULL,
650 0,0, // dest, bit instruction
652 0, // literal operand
654 0, // fast call/return mode select bit
660 pCodeInstruction pic16_pciCALL = {
661 {PC_OPCODE, NULL, NULL, 0, NULL,
674 0,0, // dest, bit instruction
676 0, // literal operand
678 1, // fast call/return mode select bit
684 pCodeInstruction pic16_pciCOMF = {
685 {PC_OPCODE, NULL, NULL, 0, NULL,
698 1,0, // dest, bit instruction
700 0, // literal operand
702 0, // fast call/return mode select bit
704 PCC_REGISTER, // inCond
705 PCC_REGISTER // outCond
708 pCodeInstruction pic16_pciCOMFW = {
709 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,0, // dest, bit instruction
724 0, // literal operand
726 0, // fast call/return mode select bit
728 PCC_REGISTER, // inCond
732 pCodeInstruction pic16_pciCLRF = {
733 {PC_OPCODE, NULL, NULL, 0, NULL,
746 0,0, // dest, bit instruction
748 0, // literal operand
750 0, // fast call/return mode select bit
752 PCC_REGISTER, // inCond
753 PCC_REGISTER // outCond
756 pCodeInstruction pic16_pciCLRWDT = {
757 {PC_OPCODE, NULL, NULL, 0, NULL,
770 0,0, // dest, bit instruction
772 0, // literal operand
774 0, // fast call/return mode select bit
780 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
781 {PC_OPCODE, NULL, NULL, 0, NULL,
794 0,0, // dest, bit instruction
796 0, // literal operand
798 0, // fast call/return mode select bit
800 (PCC_W | PCC_REGISTER), // inCond
804 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
805 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 0, // literal operand
822 0, // fast call/return mode select bit
824 (PCC_W | PCC_REGISTER), // inCond
828 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
829 {PC_OPCODE, NULL, NULL, 0, NULL,
842 1,0, // dest, bit instruction
844 0, // literal operand
846 0, // fast call/return mode select bit
848 (PCC_W | PCC_REGISTER), // inCond
852 pCodeInstruction pic16_pciDAW = {
853 {PC_OPCODE, NULL, NULL, 0, NULL,
866 0,0, // dest, bit instruction
868 0, // literal operand
870 0, // fast call/return mode select bit
873 (PCC_W | PCC_C) // outCond
876 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
877 {PC_OPCODE, NULL, NULL, 0, NULL,
890 1,0, // dest, bit instruction
892 0, // literal operand
894 0, // fast call/return mode select bit
896 PCC_REGISTER, // inCond
897 PCC_REGISTER // outCond
900 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
901 {PC_OPCODE, NULL, NULL, 0, NULL,
914 0,0, // dest, bit instruction
916 0, // literal operand
918 0, // fast call/return mode select bit
920 PCC_REGISTER, // inCond
924 pCodeInstruction pic16_pciDECF = {
925 {PC_OPCODE, NULL, NULL, 0, NULL,
938 1,0, // dest, bit instruction
940 0, // literal operand
942 0, // fast call/return mode select bit
944 PCC_REGISTER, // inCond
945 PCC_REGISTER // outCond
948 pCodeInstruction pic16_pciDECFW = {
949 {PC_OPCODE, NULL, NULL, 0, NULL,
962 0,0, // dest, bit instruction
964 0, // literal operand
966 0, // fast call/return mode select bit
968 PCC_REGISTER, // inCond
972 pCodeInstruction pic16_pciDECFSZ = {
973 {PC_OPCODE, NULL, NULL, 0, NULL,
986 1,0, // dest, bit instruction
988 0, // literal operand
990 0, // fast call/return mode select bit
992 PCC_REGISTER, // inCond
993 PCC_REGISTER // outCond
996 pCodeInstruction pic16_pciDECFSZW = {
997 {PC_OPCODE, NULL, NULL, 0, NULL,
1003 NULL, // from branch
1010 0,0, // dest, bit instruction
1011 1,1, // branch, skip
1012 0, // literal operand
1013 1, // RAM access bit
1014 0, // fast call/return mode select bit
1016 PCC_REGISTER, // inCond
1020 pCodeInstruction pic16_pciGOTO = {
1021 {PC_OPCODE, NULL, NULL, 0, NULL,
1027 NULL, // from branch
1034 0,0, // dest, bit instruction
1035 1,0, // branch, skip
1036 0, // literal operand
1037 0, // RAM access bit
1038 0, // fast call/return mode select bit
1040 PCC_REL_ADDR, // inCond
1044 pCodeInstruction pic16_pciINCF = {
1045 {PC_OPCODE, NULL, NULL, 0, NULL,
1051 NULL, // from branch
1058 1,0, // dest, bit instruction
1059 0,0, // branch, skip
1060 0, // literal operand
1061 1, // RAM access bit
1062 0, // fast call/return mode select bit
1064 PCC_REGISTER, // inCond
1065 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1068 pCodeInstruction pic16_pciINCFW = {
1069 {PC_OPCODE, NULL, NULL, 0, NULL,
1075 NULL, // from branch
1082 0,0, // dest, bit instruction
1083 0,0, // branch, skip
1084 0, // literal operand
1085 1, // RAM access bit
1086 0, // fast call/return mode select bit
1088 PCC_REGISTER, // inCond
1092 pCodeInstruction pic16_pciINCFSZ = {
1093 {PC_OPCODE, NULL, NULL, 0, NULL,
1099 NULL, // from branch
1106 1,0, // dest, bit instruction
1107 1,1, // branch, skip
1108 0, // literal operand
1109 1, // RAM access bit
1110 0, // fast call/return mode select bit
1112 PCC_REGISTER, // inCond
1113 PCC_REGISTER // outCond
1116 pCodeInstruction pic16_pciINCFSZW = {
1117 {PC_OPCODE, NULL, NULL, 0, NULL,
1123 NULL, // from branch
1130 0,0, // dest, bit instruction
1131 1,1, // branch, skip
1132 0, // literal operand
1133 1, // RAM access bit
1134 0, // fast call/return mode select bit
1136 PCC_REGISTER, // inCond
1140 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1141 {PC_OPCODE, NULL, NULL, 0, NULL,
1147 NULL, // from branch
1154 1,0, // dest, bit instruction
1155 1,1, // branch, skip
1156 0, // literal operand
1157 1, // RAM access bit
1158 0, // fast call/return mode select bit
1160 PCC_REGISTER, // inCond
1161 PCC_REGISTER // outCond
1164 pCodeInstruction pic16_pciIORWF = {
1165 {PC_OPCODE, NULL, NULL, 0, NULL,
1171 NULL, // from branch
1178 1,0, // dest, bit instruction
1179 0,0, // branch, skip
1180 0, // literal operand
1181 1, // RAM access bit
1182 0, // fast call/return mode select bit
1184 (PCC_W | PCC_REGISTER), // inCond
1185 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1188 pCodeInstruction pic16_pciIORFW = {
1189 {PC_OPCODE, NULL, NULL, 0, NULL,
1195 NULL, // from branch
1202 0,0, // dest, bit instruction
1203 0,0, // branch, skip
1204 0, // literal operand
1205 1, // RAM access bit
1206 0, // fast call/return mode select bit
1208 (PCC_W | PCC_REGISTER), // inCond
1209 (PCC_W | PCC_Z | PCC_N) // outCond
1212 pCodeInstruction pic16_pciIORLW = {
1213 {PC_OPCODE, NULL, NULL, 0, NULL,
1219 NULL, // from branch
1226 0,0, // dest, bit instruction
1227 0,0, // branch, skip
1228 1, // literal operand
1229 0, // RAM access bit
1230 0, // fast call/return mode select bit
1232 (PCC_W | PCC_LITERAL), // inCond
1233 (PCC_W | PCC_Z | PCC_N) // outCond
1236 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1237 {PC_OPCODE, NULL, NULL, 0, NULL,
1243 NULL, // from branch
1250 0,0, // dest, bit instruction
1251 0,0, // branch, skip
1252 1, // literal operand
1253 0, // RAM access bit
1254 0, // fast call/return mode select bit
1256 (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
1257 // f (identifies FSRx)?
1258 PCC_REGISTER // outCond
1261 pCodeInstruction pic16_pciMOVF = {
1262 {PC_OPCODE, NULL, NULL, 0, NULL,
1268 NULL, // from branch
1275 1,0, // dest, bit instruction
1276 0,0, // branch, skip
1277 0, // literal operand
1278 1, // RAM access bit
1279 0, // fast call/return mode select bit
1281 PCC_REGISTER, // inCond
1282 (PCC_Z | PCC_N) // outCond
1285 pCodeInstruction pic16_pciMOVFW = {
1286 {PC_OPCODE, NULL, NULL, 0, NULL,
1292 NULL, // from branch
1299 0,0, // dest, bit instruction
1300 0,0, // branch, skip
1301 0, // literal operand
1302 1, // RAM access bit
1303 0, // fast call/return mode select bit
1305 PCC_REGISTER, // inCond
1306 (PCC_W | PCC_Z) // outCond
1309 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1310 {PC_OPCODE, NULL, NULL, 0, NULL,
1316 NULL, // from branch
1323 0,0, // dest, bit instruction
1324 0,0, // branch, skip
1325 0, // literal operand
1326 0, // RAM access bit
1327 0, // fast call/return mode select bit
1329 PCC_REGISTER, // inCond
1330 PCC_REGISTER2 // outCond
1333 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1334 {PC_OPCODE, NULL, NULL, 0, NULL,
1339 NULL, // from branch
1346 0,0, // dest, bit instruction
1347 0,0, // branch, skip
1348 1, // literal operand
1349 0, // RAM access bit
1350 0, // fast call/return mode select bit
1352 (PCC_NONE | PCC_LITERAL), // inCond
1353 PCC_REGISTER // outCond - BSR
1356 pCodeInstruction pic16_pciMOVLW = {
1357 {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
1375 (PCC_NONE | PCC_LITERAL), // inCond
1379 pCodeInstruction pic16_pciMOVWF = {
1380 {PC_OPCODE, NULL, NULL, 0, NULL,
1386 NULL, // from branch
1393 0,0, // dest, bit instruction
1394 0,0, // branch, skip
1395 0, // literal operand
1396 1, // RAM access bit
1397 0, // fast call/return mode select bit
1399 PCC_REGISTER, // inCond
1403 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1404 {PC_OPCODE, NULL, NULL, 0, NULL,
1409 NULL, // from branch
1416 0,0, // dest, bit instruction
1417 0,0, // branch, skip
1418 1, // literal operand
1419 0, // RAM access bit
1420 0, // fast call/return mode select bit
1422 (PCC_W | PCC_LITERAL), // inCond
1423 PCC_REGISTER // outCond - PROD
1426 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1427 {PC_OPCODE, NULL, NULL, 0, NULL,
1432 NULL, // from branch
1439 0,0, // dest, bit instruction
1440 0,0, // branch, skip
1441 0, // literal operand
1442 1, // RAM access bit
1443 0, // fast call/return mode select bit
1445 (PCC_W | PCC_REGISTER), // inCond
1446 PCC_REGISTER // outCond - PROD
1449 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1450 {PC_OPCODE, NULL, NULL, 0, NULL,
1455 NULL, // from branch
1462 0,0, // dest, bit instruction
1463 0,0, // branch, skip
1464 0, // literal operand
1465 1, // RAM access bit
1466 0, // fast call/return mode select bit
1468 PCC_REGISTER, // inCond
1469 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1472 pCodeInstruction pic16_pciNOP = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1478 NULL, // from branch
1485 0,0, // dest, bit instruction
1486 0,0, // branch, skip
1487 0, // literal operand
1488 0, // RAM access bit
1489 0, // fast call/return mode select bit
1495 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1496 {PC_OPCODE, NULL, NULL, 0, NULL,
1501 NULL, // from branch
1508 0,0, // dest, bit instruction
1509 0,0, // branch, skip
1510 0, // literal operand
1511 0, // RAM access bit
1512 0, // fast call/return mode select bit
1518 pCodeInstruction pic16_pciPUSH = {
1519 {PC_OPCODE, NULL, NULL, 0, NULL,
1524 NULL, // from branch
1531 0,0, // dest, bit instruction
1532 0,0, // branch, skip
1533 0, // literal operand
1534 0, // RAM access bit
1535 0, // fast call/return mode select bit
1541 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1542 {PC_OPCODE, NULL, NULL, 0, NULL,
1547 NULL, // from branch
1554 0,0, // dest, bit instruction
1555 0,0, // branch, skip
1556 0, // literal operand
1557 0, // RAM access bit
1558 0, // fast call/return mode select bit
1560 PCC_REL_ADDR, // inCond
1564 pCodeInstruction pic16_pciRETFIE = {
1565 {PC_OPCODE, NULL, NULL, 0, NULL,
1571 NULL, // from branch
1578 0,0, // dest, bit instruction
1579 1,0, // branch, skip
1580 0, // literal operand
1581 0, // RAM access bit
1582 1, // fast call/return mode select bit
1585 PCC_NONE // outCond (not true... affects the GIE bit too)
1588 pCodeInstruction pic16_pciRETLW = {
1589 {PC_OPCODE, NULL, NULL, 0, NULL,
1595 NULL, // from branch
1602 0,0, // dest, bit instruction
1603 1,0, // branch, skip
1604 1, // literal operand
1605 0, // RAM access bit
1606 0, // fast call/return mode select bit
1608 PCC_LITERAL, // inCond
1612 pCodeInstruction pic16_pciRETURN = {
1613 {PC_OPCODE, NULL, NULL, 0, NULL,
1619 NULL, // from branch
1626 0,0, // dest, bit instruction
1627 1,0, // branch, skip
1628 0, // literal operand
1629 0, // RAM access bit
1630 1, // fast call/return mode select bit
1635 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1636 {PC_OPCODE, NULL, NULL, 0, NULL,
1642 NULL, // from branch
1649 1,0, // dest, bit instruction
1650 0,0, // branch, skip
1651 0, // literal operand
1652 1, // RAM access bit
1653 0, // fast call/return mode select bit
1655 (PCC_C | PCC_REGISTER), // inCond
1656 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1659 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1660 {PC_OPCODE, NULL, NULL, 0, NULL,
1666 NULL, // from branch
1673 0,0, // dest, bit instruction
1674 0,0, // branch, skip
1675 0, // literal operand
1676 1, // RAM access bit
1677 0, // fast call/return mode select bit
1679 (PCC_C | PCC_REGISTER), // inCond
1680 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1683 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1684 {PC_OPCODE, NULL, NULL, 0, NULL,
1690 NULL, // from branch
1697 1,0, // dest, bit instruction
1698 0,0, // branch, skip
1699 0, // literal operand
1700 1, // RAM access bit
1701 0, // fast call/return mode select bit
1703 PCC_REGISTER, // inCond
1704 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1706 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1707 {PC_OPCODE, NULL, NULL, 0, NULL,
1713 NULL, // from branch
1720 0,0, // dest, bit instruction
1721 0,0, // branch, skip
1722 0, // literal operand
1723 1, // RAM access bit
1724 0, // fast call/return mode select bit
1726 PCC_REGISTER, // inCond
1727 (PCC_W | PCC_Z | PCC_N) // outCond
1729 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1730 {PC_OPCODE, NULL, NULL, 0, NULL,
1736 NULL, // from branch
1743 1,0, // dest, bit instruction
1744 0,0, // branch, skip
1745 0, // literal operand
1746 1, // RAM access bit
1747 0, // fast call/return mode select bit
1749 (PCC_C | PCC_REGISTER), // inCond
1750 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1752 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1753 {PC_OPCODE, NULL, NULL, 0, NULL,
1759 NULL, // from branch
1766 0,0, // dest, bit instruction
1767 0,0, // branch, skip
1768 0, // literal operand
1769 1, // RAM access bit
1770 0, // fast call/return mode select bit
1772 (PCC_C | PCC_REGISTER), // inCond
1773 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1775 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1776 {PC_OPCODE, NULL, NULL, 0, NULL,
1782 NULL, // from branch
1789 1,0, // dest, bit instruction
1790 0,0, // branch, skip
1791 0, // literal operand
1792 1, // RAM access bit
1793 0, // fast call/return mode select bit
1795 PCC_REGISTER, // inCond
1796 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1799 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
1800 {PC_OPCODE, NULL, NULL, 0, NULL,
1806 NULL, // from branch
1813 0,0, // dest, bit instruction
1814 0,0, // branch, skip
1815 0, // literal operand
1816 1, // RAM access bit
1817 0, // fast call/return mode select bit
1819 PCC_REGISTER, // inCond
1820 (PCC_W | PCC_Z | PCC_N) // outCond
1823 pCodeInstruction pic16_pciSETF = { // mdubuc - New
1824 {PC_OPCODE, NULL, NULL, 0, NULL,
1830 NULL, // from branch
1837 0,0, // dest, bit instruction
1838 0,0, // branch, skip
1839 0, // literal operand
1840 1, // RAM access bit
1841 0, // fast call/return mode select bit
1843 PCC_REGISTER, // inCond
1844 PCC_REGISTER // outCond
1847 pCodeInstruction pic16_pciSUBLW = {
1848 {PC_OPCODE, NULL, NULL, 0, NULL,
1854 NULL, // from branch
1861 0,0, // dest, bit instruction
1862 0,0, // branch, skip
1863 1, // literal operand
1864 0, // RAM access bit
1865 0, // fast call/return mode select bit
1867 (PCC_W | PCC_LITERAL), // inCond
1868 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1871 pCodeInstruction pic16_pciSUBFWB = {
1872 {PC_OPCODE, NULL, NULL, 0, NULL,
1878 NULL, // from branch
1885 1,0, // dest, bit instruction
1886 0,0, // branch, skip
1887 0, // literal operand
1888 1, // RAM access bit
1889 0, // fast call/return mode select bit
1891 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1892 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1895 pCodeInstruction pic16_pciSUBWF = {
1896 {PC_OPCODE, NULL, NULL, 0, NULL,
1902 NULL, // from branch
1909 1,0, // dest, bit instruction
1910 0,0, // branch, skip
1911 0, // literal operand
1912 1, // RAM access bit
1913 0, // fast call/return mode select bit
1915 (PCC_W | PCC_REGISTER), // inCond
1916 (PCC_REGISTER | PCC_Z) // outCond
1919 pCodeInstruction pic16_pciSUBFW = {
1920 {PC_OPCODE, NULL, NULL, 0, NULL,
1926 NULL, // from branch
1933 0,0, // dest, bit instruction
1934 0,0, // branch, skip
1935 0, // literal operand
1936 1, // RAM access bit
1937 0, // fast call/return mode select bit
1939 (PCC_W | PCC_REGISTER), // inCond
1940 (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
1943 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
1944 {PC_OPCODE, NULL, NULL, 0, NULL,
1950 NULL, // from branch
1957 1,0, // dest, bit instruction
1958 0,0, // branch, skip
1959 0, // literal operand
1960 1, // RAM access bit
1961 0, // fast call/return mode select bit
1963 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1964 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1967 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
1968 {PC_OPCODE, NULL, NULL, 0, NULL,
1974 NULL, // from branch
1981 0,0, // dest, bit instruction
1982 0,0, // branch, skip
1983 0, // literal operand
1984 1, // RAM access bit
1985 0, // fast call/return mode select bit
1987 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1988 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1991 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
1992 {PC_OPCODE, NULL, NULL, 0, NULL,
1998 NULL, // from branch
2005 1,0, // dest, bit instruction
2006 0,0, // branch, skip
2007 0, // literal operand
2008 1, // RAM access bit
2009 0, // fast call/return mode select bit
2011 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2012 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2015 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2016 {PC_OPCODE, NULL, NULL, 0, NULL,
2022 NULL, // from branch
2029 0,0, // dest, bit instruction
2030 0,0, // branch, skip
2031 0, // literal operand
2032 1, // RAM access bit
2033 0, // fast call/return mode select bit
2035 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2036 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2039 pCodeInstruction pic16_pciSWAPF = {
2040 {PC_OPCODE, NULL, NULL, 0, NULL,
2046 NULL, // from branch
2053 1,0, // dest, bit instruction
2054 0,0, // branch, skip
2055 0, // literal operand
2056 1, // RAM access bit
2057 0, // fast call/return mode select bit
2059 (PCC_REGISTER), // inCond
2060 (PCC_REGISTER) // outCond
2063 pCodeInstruction pic16_pciSWAPFW = {
2064 {PC_OPCODE, NULL, NULL, 0, NULL,
2070 NULL, // from branch
2077 0,0, // dest, bit instruction
2078 0,0, // branch, skip
2079 0, // literal operand
2080 1, // RAM access bit
2081 0, // fast call/return mode select bit
2083 (PCC_REGISTER), // inCond
2087 // mdubuc - Remove TRIS
2089 pCodeInstruction pic16_pciTRIS = {
2090 {PC_OPCODE, NULL, NULL, 0, NULL,
2096 NULL, // from branch
2103 0,0, // dest, bit instruction
2104 0,0, // branch, skip
2105 0, // literal operand
2108 PCC_REGISTER // outCond
2111 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2112 {PC_OPCODE, NULL, NULL, 0, NULL,
2118 NULL, // from branch
2125 0,0, // dest, bit instruction
2126 1,1, // branch, skip
2127 0, // literal operand
2128 1, // RAM access bit
2129 0, // fast call/return mode select bit
2131 PCC_REGISTER, // inCond
2135 pCodeInstruction pic16_pciXORWF = {
2136 {PC_OPCODE, NULL, NULL, 0, NULL,
2142 NULL, // from branch
2149 1,0, // dest, bit instruction
2150 0,0, // branch, skip
2151 0, // literal operand
2152 1, // RAM access bit
2153 0, // fast call/return mode select bit
2155 (PCC_W | PCC_REGISTER), // inCond
2156 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
2159 pCodeInstruction pic16_pciXORFW = {
2160 {PC_OPCODE, NULL, NULL, 0, NULL,
2166 NULL, // from branch
2173 0,0, // dest, bit instruction
2174 0,0, // branch, skip
2175 0, // literal operand
2176 1, // RAM access bit
2177 0, // fast call/return mode select bit
2179 (PCC_W | PCC_REGISTER), // inCond
2180 (PCC_W | PCC_Z | PCC_N) // outCond
2183 pCodeInstruction pic16_pciXORLW = {
2184 {PC_OPCODE, NULL, NULL, 0, NULL,
2190 NULL, // from branch
2197 0,0, // dest, bit instruction
2198 0,0, // branch, skip
2199 1, // literal operand
2200 1, // RAM access bit
2201 0, // fast call/return mode select bit
2203 (PCC_W | PCC_LITERAL), // inCond
2204 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
2208 #define MAX_PIC16MNEMONICS 100
2209 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2212 /* This definition needs to be part of configure.in */
2213 // #define USE_VSNPRINTF
2215 #ifdef USE_VSNPRINTF
2216 // Alas, vsnprintf is not ANSI standard, and does not exist
2217 // on Solaris (and probably other non-Gnu flavored Unixes).
2219 /*-----------------------------------------------------------------*/
2220 /* SAFE_snprintf - like snprintf except the string pointer is */
2221 /* after the string has been printed to. This is */
2222 /* useful for printing to string as though if it */
2223 /* were a stream. */
2224 /*-----------------------------------------------------------------*/
2225 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2233 va_start(val, format);
2235 vsnprintf(*str, *size, format, val);
2241 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2242 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2250 #else // USE_VSNPRINTF
2252 // This version is *not* safe, despite the name.
2254 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2258 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2263 va_start(val, format);
2265 vsprintf(buffer, format, val);
2268 len = strlen(buffer);
2270 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2271 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2274 strcpy(*str, buffer);
2280 #endif // USE_VSNPRINTF
2282 #endif // OPT_DISABLE_PIC
2285 extern void pic16_initStack(int base_address, int size);
2286 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2287 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2288 extern void pic16_init_pic(char *);
2290 void pic16_pCodeInitRegisters(void)
2292 static int initialized=0;
2298 pic16_initStack(0xfff, 8);
2299 pic16_init_pic(port->processor);
2301 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
2302 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2303 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
2304 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2305 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2306 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2307 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2309 pic16_pc_status.rIdx = IDX_STATUS;
2310 pic16_pc_fsr0.rIdx = IDX_FSR0;
2311 pic16_pc_indf0.rIdx = IDX_INDF0;
2312 pic16_pc_intcon.rIdx = IDX_INTCON;
2313 pic16_pc_pcl.rIdx = IDX_PCL;
2314 pic16_pc_pclath.rIdx = IDX_PCLATH;
2315 pic16_pc_wreg.rIdx = IDX_WREG;
2317 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2318 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2319 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2321 pic16_pc_kzero.rIdx = IDX_KZ;
2322 pic16_pc_wsave.rIdx = IDX_WSAVE;
2323 pic16_pc_ssave.rIdx = IDX_SSAVE;
2325 /* probably should put this in a separate initialization routine */
2326 pb_dead_pcodes = newpBlock();
2331 /*-----------------------------------------------------------------*/
2332 /* mnem2key - convert a pic mnemonic into a hash key */
2333 /* (BTW - this spreads the mnemonics quite well) */
2335 /*-----------------------------------------------------------------*/
2337 int mnem2key(char const *mnem)
2346 key += toupper(*mnem++) +1;
2350 return (key & 0x1f);
2353 #endif // OPT_DISABLE_PIC
2355 void pic16initMnemonics(void)
2360 pCodeInstruction *pci;
2362 if(mnemonics_initialized)
2365 // NULL out the array before making the assignments
2366 // since we check the array contents below this initialization.
2368 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2369 pic16Mnemonics[i] = NULL;
2372 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2373 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2374 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2375 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2376 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2377 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2378 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2379 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2380 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2381 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2382 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2383 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2384 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2385 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2386 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2387 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2388 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2389 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2390 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2391 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2392 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2393 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2394 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2395 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2396 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2397 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2398 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2399 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2400 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2401 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2402 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2403 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2404 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2405 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2406 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2407 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2408 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2409 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2410 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2411 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2412 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2413 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2414 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2415 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2416 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2417 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2418 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2419 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2420 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2421 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2422 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2423 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2424 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2425 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2426 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2427 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2428 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2429 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2430 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2431 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2432 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2433 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2434 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2435 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2436 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2437 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2438 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2439 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2440 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2441 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2442 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2443 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2444 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2445 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2446 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2447 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2448 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2449 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2450 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2451 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2452 pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
2453 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2454 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2455 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2456 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2458 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2459 if(pic16Mnemonics[i])
2460 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2461 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2464 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2465 pci = hTabNextItem(pic16MnemonicsHash, &key);
2468 mnemonics_initialized = 1;
2471 int pic16_getpCodePeepCommand(char *cmd);
2473 int pic16_getpCode(char *mnem,unsigned dest)
2476 pCodeInstruction *pci;
2477 int key = mnem2key(mnem);
2479 if(!mnemonics_initialized)
2480 pic16initMnemonics();
2482 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2486 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2487 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
2488 (pci->num_ops <= 2 && pci->isAccess) ||
2489 (pci->num_ops <= 2 && pci->isFastCall))
2493 pci = hTabNextItemWK (pic16MnemonicsHash);
2500 /*-----------------------------------------------------------------*
2501 * pic16initpCodePeepCommands
2503 *-----------------------------------------------------------------*/
2504 void pic16initpCodePeepCommands(void)
2512 hTabAddItem(&pic16pCodePeepCommandsHash,
2513 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2515 } while (peepCommands[i].cmd);
2517 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2520 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2521 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2526 /*-----------------------------------------------------------------
2529 *-----------------------------------------------------------------*/
2531 int pic16_getpCodePeepCommand(char *cmd)
2535 int key = mnem2key(cmd);
2538 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2541 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2542 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2546 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2553 static char getpBlock_dbName(pBlock *pb)
2559 return pb->cmemmap->dbName;
2563 void pic16_pBlockConvert2ISR(pBlock *pb)
2574 /*-----------------------------------------------------------------*/
2575 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2576 /* instances to the front of the doubly linked */
2577 /* list of pBlocks */
2578 /*-----------------------------------------------------------------*/
2580 void pic16_movepBlock2Head(char dbName)
2584 pb = the_pFile->pbHead;
2588 if(getpBlock_dbName(pb) == dbName) {
2589 pBlock *pbn = pb->next;
2590 pb->next = the_pFile->pbHead;
2591 the_pFile->pbHead->prev = pb;
2592 the_pFile->pbHead = pb;
2595 pb->prev->next = pbn;
2597 // If the pBlock that we just moved was the last
2598 // one in the link of all of the pBlocks, then we
2599 // need to point the tail to the block just before
2600 // the one we moved.
2601 // Note: if pb->next is NULL, then pb must have
2602 // been the last pBlock in the chain.
2605 pbn->prev = pb->prev;
2607 the_pFile->pbTail = pb->prev;
2618 void pic16_copypCode(FILE *of, char dbName)
2622 if(!of || !the_pFile)
2625 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2626 if(getpBlock_dbName(pb) == dbName) {
2628 pic16_printpBlock(of,pb);
2633 void pic16_pcode_test(void)
2636 DFPRINTF((stderr,"pcode is alive!\n"));
2646 /* create the file name */
2647 strcpy(buffer,dstFileName);
2648 strcat(buffer,".p");
2650 if( !(pFile = fopen(buffer, "w" ))) {
2651 werror(E_FILE_OPEN_ERR,buffer);
2655 fprintf(pFile,"pcode dump\n\n");
2657 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2658 fprintf(pFile,"\n\tNew pBlock\n\n");
2660 fprintf(pFile,"%s",pb->cmemmap->sname);
2662 fprintf(pFile,"internal pblock");
2664 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2665 pic16_printpBlock(pFile,pb);
2669 /*-----------------------------------------------------------------*/
2670 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2671 /* ister, RegCond will return the bit being referenced. */
2673 /* fixme - why not just OR in the pcop bit field */
2674 /*-----------------------------------------------------------------*/
2676 static int RegCond(pCodeOp *pcop)
2682 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2683 switch(PCORB(pcop)->bit) {
2697 /*-----------------------------------------------------------------*/
2698 /* pic16_newpCode - create and return a newly initialized pCode */
2700 /* fixme - rename this */
2702 /* The purpose of this routine is to create a new Instruction */
2703 /* pCode. This is called by gen.c while the assembly code is being */
2707 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2708 /* (note that the op is analogous to but not the */
2709 /* same thing as the opcode of the instruction.) */
2710 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2713 /* a pointer to the new malloc'd pCode is returned. */
2717 /*-----------------------------------------------------------------*/
2718 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2720 pCodeInstruction *pci ;
2722 if(!mnemonics_initialized)
2723 pic16initMnemonics();
2725 pci = Safe_calloc(1, sizeof(pCodeInstruction));
2727 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
2728 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
2731 if(pci->inCond & PCC_EXAMINE_PCOP)
2732 pci->inCond |= RegCond(pcop);
2734 if(pci->outCond & PCC_EXAMINE_PCOP)
2735 pci->outCond |= RegCond(pcop);
2737 pci->pc.prev = pci->pc.next = NULL;
2738 return (pCode *)pci;
2741 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2747 /*-----------------------------------------------------------------*/
2748 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
2750 /* Wild pcodes are used during the peep hole optimizer to serve */
2751 /* as place holders for any instruction. When a snippet of code is */
2752 /* compared to a peep hole rule, the wild card opcode will match */
2753 /* any instruction. However, the optional operand and label are */
2754 /* additional qualifiers that must also be matched before the */
2755 /* line (of assembly code) is declared matched. Note that the */
2756 /* operand may be wild too. */
2758 /* Note, a wild instruction is specified just like a wild var: */
2759 /* %4 ; A wild instruction, */
2760 /* See the peeph.def file for additional examples */
2762 /*-----------------------------------------------------------------*/
2764 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2769 pcw = Safe_calloc(1,sizeof(pCodeWild));
2771 pcw->pci.pc.type = PC_WILD;
2772 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2773 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2774 pcw->pci.pc.pb = NULL;
2776 // pcw->pci.pc.analyze = genericAnalyze;
2777 pcw->pci.pc.destruct = genericDestruct;
2778 pcw->pci.pc.print = genericPrint;
2780 pcw->id = pCodeID; // this is the 'n' in %n
2781 pcw->operand = optional_operand;
2782 pcw->label = optional_label;
2784 pcw->mustBeBitSkipInst = 0;
2785 pcw->mustNotBeBitSkipInst = 0;
2786 pcw->invertBitSkipInst = 0;
2788 return ( (pCode *)pcw);
2792 /*-----------------------------------------------------------------*/
2793 /* newPcodeInlineP - create a new pCode from a char string */
2794 /*-----------------------------------------------------------------*/
2797 pCode *pic16_newpCodeInlineP(char *cP)
2802 pcc = Safe_calloc(1,sizeof(pCodeComment));
2804 pcc->pc.type = PC_INLINE;
2805 pcc->pc.prev = pcc->pc.next = NULL;
2806 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2809 // pcc->pc.analyze = genericAnalyze;
2810 pcc->pc.destruct = genericDestruct;
2811 pcc->pc.print = genericPrint;
2814 pcc->comment = Safe_strdup(cP);
2816 pcc->comment = NULL;
2818 return ( (pCode *)pcc);
2822 /*-----------------------------------------------------------------*/
2823 /* newPcodeCharP - create a new pCode from a char string */
2824 /*-----------------------------------------------------------------*/
2826 pCode *pic16_newpCodeCharP(char *cP)
2831 pcc = Safe_calloc(1,sizeof(pCodeComment));
2833 pcc->pc.type = PC_COMMENT;
2834 pcc->pc.prev = pcc->pc.next = NULL;
2835 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2838 // pcc->pc.analyze = genericAnalyze;
2839 pcc->pc.destruct = genericDestruct;
2840 pcc->pc.print = genericPrint;
2843 pcc->comment = Safe_strdup(cP);
2845 pcc->comment = NULL;
2847 return ( (pCode *)pcc);
2851 /*-----------------------------------------------------------------*/
2852 /* pic16_newpCodeFunction - */
2853 /*-----------------------------------------------------------------*/
2856 pCode *pic16_newpCodeFunction(char *mod,char *f)
2860 pcf = Safe_calloc(1,sizeof(pCodeFunction));
2861 //_ALLOC(pcf,sizeof(pCodeFunction));
2863 pcf->pc.type = PC_FUNCTION;
2864 pcf->pc.prev = pcf->pc.next = NULL;
2865 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2868 // pcf->pc.analyze = genericAnalyze;
2869 pcf->pc.destruct = genericDestruct;
2870 pcf->pc.print = pCodePrintFunction;
2875 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
2876 pcf->modname = Safe_calloc(1,strlen(mod)+1);
2877 strcpy(pcf->modname,mod);
2879 pcf->modname = NULL;
2882 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
2883 pcf->fname = Safe_calloc(1,strlen(f)+1);
2884 strcpy(pcf->fname,f);
2888 return ( (pCode *)pcf);
2892 /*-----------------------------------------------------------------*/
2893 /* pic16_newpCodeFlow */
2894 /*-----------------------------------------------------------------*/
2895 static void destructpCodeFlow(pCode *pc)
2897 if(!pc || !isPCFL(pc))
2904 pic16_unlinkpCode(pc);
2906 deleteSet(&PCFL(pc)->registers);
2907 deleteSet(&PCFL(pc)->from);
2908 deleteSet(&PCFL(pc)->to);
2913 pCode *pic16_newpCodeFlow(void )
2917 //_ALLOC(pcflow,sizeof(pCodeFlow));
2918 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
2920 pcflow->pc.type = PC_FLOW;
2921 pcflow->pc.prev = pcflow->pc.next = NULL;
2922 pcflow->pc.pb = NULL;
2924 // pcflow->pc.analyze = genericAnalyze;
2925 pcflow->pc.destruct = destructpCodeFlow;
2926 pcflow->pc.print = genericPrint;
2928 pcflow->pc.seq = GpcFlowSeq++;
2930 pcflow->from = pcflow->to = NULL;
2932 pcflow->inCond = PCC_NONE;
2933 pcflow->outCond = PCC_NONE;
2935 pcflow->firstBank = -1;
2936 pcflow->lastBank = -1;
2938 pcflow->FromConflicts = 0;
2939 pcflow->ToConflicts = 0;
2943 pcflow->registers = newSet();
2945 return ( (pCode *)pcflow);
2949 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
2953 pCodeFlowLink *pcflowLink;
2955 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2957 pcflowLink->pcflow = pcflow;
2958 pcflowLink->bank_conflict = 0;
2963 /*-----------------------------------------------------------------*/
2964 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
2965 /*-----------------------------------------------------------------*/
2967 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
2972 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2974 pccs->pc.type = PC_CSOURCE;
2975 pccs->pc.prev = pccs->pc.next = NULL;
2978 pccs->pc.destruct = genericDestruct;
2979 pccs->pc.print = genericPrint;
2981 pccs->line_number = ln;
2983 pccs->line = Safe_strdup(l);
2988 pccs->file_name = Safe_strdup(f);
2990 pccs->file_name = NULL;
2992 return ( (pCode *)pccs);
2995 /*-----------------------------------------------------------------*/
2996 /* pCodeLabelDestruct - free memory used by a label. */
2997 /*-----------------------------------------------------------------*/
2998 static void pCodeLabelDestruct(pCode *pc)
3004 if((pc->type == PC_LABEL) && PCL(pc)->label)
3005 free(PCL(pc)->label);
3011 pCode *pic16_newpCodeLabel(char *name, int key)
3017 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3019 pcl->pc.type = PC_LABEL;
3020 pcl->pc.prev = pcl->pc.next = NULL;
3021 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3024 // pcl->pc.analyze = genericAnalyze;
3025 pcl->pc.destruct = pCodeLabelDestruct;
3026 pcl->pc.print = pCodePrintLabel;
3032 sprintf(s,"_%05d_DS_",key);
3037 pcl->label = Safe_strdup(s);
3039 //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
3040 return ( (pCode *)pcl);
3045 /*-----------------------------------------------------------------*/
3046 /* newpBlock - create and return a pointer to a new pBlock */
3047 /*-----------------------------------------------------------------*/
3048 static pBlock *newpBlock(void)
3053 PpB = Safe_calloc(1,sizeof(pBlock) );
3054 PpB->next = PpB->prev = NULL;
3056 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3057 PpB->tregisters = NULL;
3059 PpB->FlowTree = NULL;
3065 /*-----------------------------------------------------------------*/
3066 /* pic16_newpCodeChain - create a new chain of pCodes */
3067 /*-----------------------------------------------------------------*
3069 * This function will create a new pBlock and the pointer to the
3070 * pCode that is passed in will be the first pCode in the block.
3071 *-----------------------------------------------------------------*/
3074 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3077 pBlock *pB = newpBlock();
3079 pB->pcHead = pB->pcTail = pc;
3086 /*-----------------------------------------------------------------*/
3087 /* pic16_newpCodeOpLabel - Create a new label given the key */
3088 /* Note, a negative key means that the label is part of wild card */
3089 /* (and hence a wild card label) used in the pCodePeep */
3090 /* optimizations). */
3091 /*-----------------------------------------------------------------*/
3093 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3096 static int label_key=-1;
3100 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3101 pcop->type = PO_LABEL;
3106 sprintf(s=buffer,"_%05d_DS_",key);
3108 s = name, key = label_key--;
3111 pcop->name = Safe_strdup(s);
3113 ((pCodeOpLabel *)pcop)->key = key;
3115 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3119 /*-----------------------------------------------------------------*/
3120 /*-----------------------------------------------------------------*/
3121 pCodeOp *pic16_newpCodeOpLit(int lit)
3127 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3128 pcop->type = PO_LITERAL;
3132 sprintf(s,"0x%02x",lit);
3134 pcop->name = Safe_strdup(s);
3137 ((pCodeOpLit *)pcop)->lit = lit;
3142 /*-----------------------------------------------------------------*/
3143 /*-----------------------------------------------------------------*/
3144 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3148 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3149 pcop->type = PO_IMMEDIATE;
3151 regs *r = pic16_dirregWithName(name);
3152 pcop->name = Safe_strdup(name);
3155 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
3156 PCOI(pcop)->rIdx = r->rIdx;
3158 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
3159 PCOI(pcop)->rIdx = -1;
3161 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3166 PCOI(pcop)->index = index;
3167 PCOI(pcop)->offset = offset;
3168 PCOI(pcop)->_const = code_space;
3173 /*-----------------------------------------------------------------*/
3174 /*-----------------------------------------------------------------*/
3175 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3181 if(!pcwb || !subtype) {
3182 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3186 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3187 pcop->type = PO_WILD;
3188 sprintf(s,"%%%d",id);
3189 pcop->name = Safe_strdup(s);
3191 PCOW(pcop)->id = id;
3192 PCOW(pcop)->pcwb = pcwb;
3193 PCOW(pcop)->subtype = subtype;
3194 PCOW(pcop)->matched = NULL;
3199 /*-----------------------------------------------------------------*/
3200 /*-----------------------------------------------------------------*/
3201 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3205 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3206 pcop->type = PO_GPR_BIT;
3208 pcop->name = Safe_strdup(s);
3212 PCORB(pcop)->bit = bit;
3213 PCORB(pcop)->inBitSpace = inBitSpace;
3215 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3216 PCOR(pcop)->r = NULL;
3217 PCOR(pcop)->rIdx = 0;
3221 /*-----------------------------------------------------------------*
3222 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3224 * If rIdx >=0 then a specific register from the set of registers
3225 * will be selected. If rIdx <0, then a new register will be searched
3227 *-----------------------------------------------------------------*/
3229 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3233 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3238 PCOR(pcop)->rIdx = rIdx;
3239 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3241 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3244 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3247 pcop->type = PCOR(pcop)->r->pc_type;
3252 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3256 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3257 PCOR(pcop)->r = pic16_allocRegByName(name, 1);
3258 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3259 pcop->type = PCOR(pcop)->r->pc_type;
3260 pcop->name = PCOR(pcop)->r->name;
3265 /*-----------------------------------------------------------------*/
3266 /*-----------------------------------------------------------------*/
3268 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3275 pcop = pic16_newpCodeOpBit(name, -1,0);
3279 pcop = pic16_newpCodeOpLit(-1);
3283 pcop = pic16_newpCodeOpLabel(NULL,-1);
3286 pcop = pic16_newpCodeOpReg(-1);
3289 case PO_GPR_REGISTER:
3291 pcop = pic16_newpCodeOpRegFromStr(name);
3293 pcop = pic16_newpCodeOpReg(-1);
3297 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3300 pcop->name = Safe_strdup(name);
3308 /*-----------------------------------------------------------------*/
3309 /*-----------------------------------------------------------------*/
3310 void pic16_pCodeConstString(char *name, char *value)
3314 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3319 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3321 pic16_addpBlock(pb);
3323 sprintf(buffer,"; %s = %s",name,value);
3325 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3326 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3329 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3335 /*-----------------------------------------------------------------*/
3336 /*-----------------------------------------------------------------*/
3338 static void pCodeReadCodeTable(void)
3342 fprintf(stderr, " %s\n",__FUNCTION__);
3344 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3346 pic16_addpBlock(pb);
3348 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3349 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3350 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3351 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3353 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3354 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3355 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3356 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3361 /*-----------------------------------------------------------------*/
3362 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3363 /*-----------------------------------------------------------------*/
3364 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3371 /* If this is the first pcode to be added to a block that
3372 * was initialized with a NULL pcode, then go ahead and
3373 * make this pcode the head and tail */
3374 pb->pcHead = pb->pcTail = pc;
3377 pb->pcTail->next = pc;
3379 pc->prev = pb->pcTail;
3386 /*-----------------------------------------------------------------*/
3387 /* pic16_addpBlock - place a pBlock into the pFile */
3388 /*-----------------------------------------------------------------*/
3389 void pic16_addpBlock(pBlock *pb)
3391 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3394 /* First time called, we'll pass through here. */
3395 //_ALLOC(the_pFile,sizeof(pFile));
3396 the_pFile = Safe_calloc(1,sizeof(pFile));
3397 the_pFile->pbHead = the_pFile->pbTail = pb;
3398 the_pFile->functions = NULL;
3402 the_pFile->pbTail->next = pb;
3403 pb->prev = the_pFile->pbTail;
3405 the_pFile->pbTail = pb;
3408 /*-----------------------------------------------------------------*/
3409 /* removepBlock - remove a pBlock from the pFile */
3410 /*-----------------------------------------------------------------*/
3411 static void removepBlock(pBlock *pb)
3419 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3421 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3424 if(pbs == the_pFile->pbHead)
3425 the_pFile->pbHead = pbs->next;
3427 if (pbs == the_pFile->pbTail)
3428 the_pFile->pbTail = pbs->prev;
3431 pbs->next->prev = pbs->prev;
3434 pbs->prev->next = pbs->next;
3441 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3445 /*-----------------------------------------------------------------*/
3446 /* printpCode - write the contents of a pCode to a file */
3447 /*-----------------------------------------------------------------*/
3448 static void printpCode(FILE *of, pCode *pc)
3459 fprintf(of,"warning - unable to print pCode\n");
3462 /*-----------------------------------------------------------------*/
3463 /* pic16_printpBlock - write the contents of a pBlock to a file */
3464 /*-----------------------------------------------------------------*/
3465 void pic16_printpBlock(FILE *of, pBlock *pb)
3475 for(pc = pb->pcHead; pc; pc = pc->next)
3480 /*-----------------------------------------------------------------*/
3482 /* pCode processing */
3486 /*-----------------------------------------------------------------*/
3488 void pic16_unlinkpCode(pCode *pc)
3494 fprintf(stderr,"Unlinking: ");
3495 printpCode(stderr, pc);
3498 pc->prev->next = pc->next;
3500 pc->next->prev = pc->prev;
3502 pc->prev = pc->next = NULL;
3506 /*-----------------------------------------------------------------*/
3507 /*-----------------------------------------------------------------*/
3509 static void genericDestruct(pCode *pc)
3512 pic16_unlinkpCode(pc);
3515 /* For instructions, tell the register (if there's one used)
3516 * that it's no longer needed */
3517 regs *reg = pic16_getRegFromInstruction(pc);
3519 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3522 /* Instead of deleting the memory used by this pCode, mark
3523 * the object as bad so that if there's a pointer to this pCode
3524 * dangling around somewhere then (hopefully) when the type is
3525 * checked we'll catch it.
3530 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3537 /*-----------------------------------------------------------------*/
3538 /*-----------------------------------------------------------------*/
3539 static void pBlockRegs(FILE *of, pBlock *pb)
3544 r = setFirstItem(pb->tregisters);
3546 r = setNextItem(pb->tregisters);
3551 /*-----------------------------------------------------------------*/
3552 /*-----------------------------------------------------------------*/
3553 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3558 int use_buffer = 1; // copy the string to the passed buffer pointer
3563 use_buffer = 0; // Don't bother copying the string to the buffer.
3567 switch(pcop->type) {
3571 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3574 return PCOR(pcop)->r->name;
3577 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3580 SAFE_snprintf(&buffer,&size,"%s",r->name);
3590 if(PCOI(pcop)->_const) {
3592 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3593 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3596 8 * PCOI(pcop)->offset );
3598 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3601 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3602 SAFE_snprintf(&s,&size,"(%s + %d)",
3604 PCOI(pcop)->index );
3606 if(PCOI(pcop)->offset)
3607 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3609 SAFE_snprintf(&s,&size,"%s",pcop->name);
3617 //size = sizeof(buffer);
3618 if( PCOR(pcop)->instance) {
3619 SAFE_snprintf(&s,&size,"(%s + %d)",
3621 PCOR(pcop)->instance );
3622 //fprintf(stderr,"PO_DIR %s\n",buffer);
3624 SAFE_snprintf(&s,&size,"%s",pcop->name);
3630 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3639 return "NO operand";
3643 /*-----------------------------------------------------------------*/
3644 /*-----------------------------------------------------------------*/
3645 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3649 return pic16_get_op(pcc->pcop,NULL,0);
3651 return ("ERROR Null: "__FUNCTION__);
3655 /*-----------------------------------------------------------------*/
3656 /*-----------------------------------------------------------------*/
3657 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3660 fprintf(of,"pcodeopprint- not implemented\n");
3663 /*-----------------------------------------------------------------*/
3664 /*-----------------------------------------------------------------*/
3665 static char *pCode2str(char *str, int size, pCode *pc)
3673 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3675 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3677 if(PCI(pc)->isBitInst) {
3678 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3679 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3680 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
3681 PCI(pc)->pcop->name ,
3682 PCI(pc)->pcop->name );
3684 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
3685 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3686 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3687 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3689 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3690 //PCI(pc)->pcop->t.bit );
3693 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3694 if( PCI(pc)->num_ops == 3)
3695 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3697 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3700 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3702 if( PCI(pc)->num_ops == 3)
3703 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3711 /* assuming that comment ends with a \n */
3712 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3716 /* assuming that inline code ends with a \n */
3717 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3721 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3724 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3727 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3730 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3733 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3737 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3744 /*-----------------------------------------------------------------*/
3745 /* genericPrint - the contents of a pCode to a file */
3746 /*-----------------------------------------------------------------*/
3747 static void genericPrint(FILE *of, pCode *pc)
3755 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3759 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3763 // If the opcode has a label, print that first
3765 pBranch *pbl = PCI(pc)->label;
3766 while(pbl && pbl->pc) {
3767 if(pbl->pc->type == PC_LABEL)
3768 pCodePrintLabel(of, pbl->pc);
3774 genericPrint(of,PCODE(PCI(pc)->cline));
3779 pCode2str(str, 256, pc);
3781 fprintf(of,"%s",str);
3784 if(pic16_debug_verbose) {
3785 fprintf(of, "\t;key=%03x",pc->seq);
3787 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3792 pBranch *dpb = pc->to; // debug
3794 switch ( dpb->pc->type) {
3796 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3799 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3802 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3805 fprintf(of, "\t;flow");
3819 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3820 if(PCW(pc)->pci.label)
3821 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3823 if(PCW(pc)->operand) {
3824 fprintf(of,";\toperand ");
3825 pCodeOpPrint(of,PCW(pc)->operand );
3830 if(pic16_debug_verbose) {
3831 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3832 if(PCFL(pc)->ancestor)
3833 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3840 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3844 fprintf(of,"unknown pCode type %d\n",pc->type);
3849 /*-----------------------------------------------------------------*/
3850 /* pCodePrintFunction - prints function begin/end */
3851 /*-----------------------------------------------------------------*/
3853 static void pCodePrintFunction(FILE *of, pCode *pc)
3859 if( ((pCodeFunction *)pc)->modname)
3860 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3862 if(PCF(pc)->fname) {
3863 pBranch *exits = PCF(pc)->to;
3865 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3868 exits = exits->next;
3871 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3874 if((PCF(pc)->from &&
3875 PCF(pc)->from->pc->type == PC_FUNCTION &&
3876 PCF(PCF(pc)->from->pc)->fname) )
3877 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3879 fprintf(of,"; exit point [can't find entry point]\n");
3882 /*-----------------------------------------------------------------*/
3883 /* pCodePrintLabel - prints label */
3884 /*-----------------------------------------------------------------*/
3886 static void pCodePrintLabel(FILE *of, pCode *pc)
3893 fprintf(of,"%s\n",PCL(pc)->label);
3894 else if (PCL(pc)->key >=0)
3895 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3897 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3900 /*-----------------------------------------------------------------*/
3901 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3902 /* remove it if it is found. */
3903 /*-----------------------------------------------------------------*/
3904 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3911 if(pcl->type == PC_OPCODE)
3912 b = PCI(pcl)->label;
3914 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3919 //fprintf (stderr, "%s \n",__FUNCTION__);
3920 //pcl->print(stderr,pcl);
3921 //pc->print(stderr,pc);
3924 //fprintf (stderr, "found label\n");
3928 bprev->next = b->next; /* Not first pCode in chain */
3932 PCI(pcl)->label = b->next; /* First pCode in chain */
3935 return; /* A label can't occur more than once */
3943 /*-----------------------------------------------------------------*/
3944 /*-----------------------------------------------------------------*/
3945 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
3964 /*-----------------------------------------------------------------*/
3965 /* pBranchLink - given two pcodes, this function will link them */
3966 /* together through their pBranches */
3967 /*-----------------------------------------------------------------*/
3968 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3972 // Declare a new branch object for the 'from' pCode.
3974 //_ALLOC(b,sizeof(pBranch));
3975 b = Safe_calloc(1,sizeof(pBranch));
3976 b->pc = PCODE(t); // The link to the 'to' pCode.
3979 f->to = pic16_pBranchAppend(f->to,b);
3981 // Now do the same for the 'to' pCode.
3983 //_ALLOC(b,sizeof(pBranch));
3984 b = Safe_calloc(1,sizeof(pBranch));
3988 t->from = pic16_pBranchAppend(t->from,b);
3993 /*-----------------------------------------------------------------*/
3994 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3996 /*-----------------------------------------------------------------*/
3997 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4010 /*-----------------------------------------------------------------*/
4011 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4012 /*-----------------------------------------------------------------*/
4013 static void pCodeUnlink(pCode *pc)
4018 if(!pc->prev || !pc->next) {
4019 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4023 /* first remove the pCode from the chain */
4024 pc->prev->next = pc->next;
4025 pc->next->prev = pc->prev;
4027 /* Now for the hard part... */
4029 /* Remove the branches */
4033 pc1 = pb1->pc; /* Get the pCode that branches to the
4034 * one we're unlinking */
4036 /* search for the link back to this pCode (the one we're
4038 if(pb2 = pBranchFind(pc1->to,pc)) {
4039 pb2->pc = pc->to->pc; // make the replacement
4041 /* if the pCode we're unlinking contains multiple 'to'
4042 * branches (e.g. this a skip instruction) then we need
4043 * to copy these extra branches to the chain. */
4045 pic16_pBranchAppend(pb2, pc->to->next);
4054 /*-----------------------------------------------------------------*/
4055 /*-----------------------------------------------------------------*/
4057 static void genericAnalyze(pCode *pc)
4067 // Go through the pCodes that are in pCode chain and link
4068 // them together through the pBranches. Note, the pCodes
4069 // are linked together as a contiguous stream like the
4070 // assembly source code lines. The linking here mimics this
4071 // except that comments are not linked in.
4073 pCode *npc = pc->next;
4075 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4076 pBranchLink(pc,npc);
4081 /* reached the end of the pcode chain without finding
4082 * an instruction we could link to. */
4086 fprintf(stderr,"analyze PC_FLOW\n");
4090 fprintf(stderr,,";A bad pCode is being used\n");
4096 /*-----------------------------------------------------------------*/
4097 /*-----------------------------------------------------------------*/
4098 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4102 if(pc->type == PC_LABEL) {
4103 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4106 if(pc->type == PC_OPCODE) {
4107 pbr = PCI(pc)->label;
4109 if(pbr->pc->type == PC_LABEL) {
4110 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4120 /*-----------------------------------------------------------------*/
4121 /*-----------------------------------------------------------------*/
4122 static int checkLabel(pCode *pc)
4126 if(pc && isPCI(pc)) {
4127 pbr = PCI(pc)->label;
4129 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4139 /*-----------------------------------------------------------------*/
4140 /* findLabelinpBlock - Search the pCode for a particular label */
4141 /*-----------------------------------------------------------------*/
4142 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4149 for(pc = pb->pcHead; pc; pc = pc->next)
4150 if(compareLabel(pc,pcop_label))
4156 /*-----------------------------------------------------------------*/
4157 /* findLabel - Search the pCode for a particular label */
4158 /*-----------------------------------------------------------------*/
4159 static pCode * findLabel(pCodeOpLabel *pcop_label)
4167 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4168 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4172 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4176 /*-----------------------------------------------------------------*/
4177 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4178 /* in the linked list */
4179 /*-----------------------------------------------------------------*/
4180 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4193 /*-----------------------------------------------------------------*/
4194 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4195 /* in the linked list */
4196 /*-----------------------------------------------------------------*/
4197 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4209 /*-----------------------------------------------------------------*/
4210 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4211 /* in the linked list */
4212 /*-----------------------------------------------------------------*/
4213 pCode * pic16_findNextInstruction(pCode *pci)
4218 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4222 fprintf(stderr,"pic16_findNextInstruction: ");
4223 printpCode(stderr, pc);
4228 //fprintf(stderr,"Couldn't find instruction\n");
4232 /*-----------------------------------------------------------------*/
4233 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4234 /* in the linked list */
4235 /*-----------------------------------------------------------------*/
4236 pCode * pic16_findPrevInstruction(pCode *pci)
4238 return findPrevpCode(pci, PC_OPCODE);
4241 /*-----------------------------------------------------------------*/
4242 /* findFunctionEnd - given a pCode find the end of the function */
4243 /* that contains it */
4244 /*-----------------------------------------------------------------*/
4245 static pCode * findFunctionEnd(pCode *pc)
4249 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4255 fprintf(stderr,"Couldn't find function end\n");
4260 /*-----------------------------------------------------------------*/
4261 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4262 /* instruction with which it is associated. */
4263 /*-----------------------------------------------------------------*/
4264 static void AnalyzeLabel(pCode *pc)
4273 static void AnalyzeGOTO(pCode *pc)
4276 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4280 static void AnalyzeSKIP(pCode *pc)
4283 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4284 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4288 static void AnalyzeRETURN(pCode *pc)
4291 // branch_link(pc,findFunctionEnd(pc->next));
4297 /*-----------------------------------------------------------------*/
4298 /*-----------------------------------------------------------------*/
4299 regs * pic16_getRegFromInstruction(pCode *pc)
4305 PCI(pc)->num_ops == 0 ||
4306 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4309 switch(PCI(pc)->pcop->type) {
4312 return PCOR(PCI(pc)->pcop)->r;
4314 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4318 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4319 return PCOR(PCI(pc)->pcop)->r;
4322 if(PCOI(PCI(pc)->pcop)->r)
4323 return (PCOI(PCI(pc)->pcop)->r);
4325 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4326 return pic16_dirregWithName(PCI(pc)->pcop->name);
4327 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4330 return PCOR(PCI(pc)->pcop)->r;
4333 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4334 return PCOR(PCI(pc)->pcop)->r;
4336 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4340 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4341 //genericPrint(stderr, pc);
4349 /*-----------------------------------------------------------------*/
4350 /*-----------------------------------------------------------------*/
4352 static void AnalyzepBlock(pBlock *pb)
4359 /* Find all of the registers used in this pBlock
4360 * by looking at each instruction and examining it's
4363 for(pc = pb->pcHead; pc; pc = pc->next) {
4365 /* Is this an instruction with operands? */
4366 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4368 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4370 /* Loop through all of the registers declared so far in
4371 this block and see if we find this one there */
4373 regs *r = setFirstItem(pb->tregisters);
4376 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4377 PCOR(PCI(pc)->pcop)->r = r;
4380 r = setNextItem(pb->tregisters);
4384 /* register wasn't found */
4385 //r = Safe_calloc(1, sizeof(regs));
4386 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4387 //addSet(&pb->tregisters, r);
4388 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4389 //PCOR(PCI(pc)->pcop)->r = r;
4390 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4392 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4395 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4396 if(PCOR(PCI(pc)->pcop)->r) {
4397 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4398 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4400 if(PCI(pc)->pcop->name)
4401 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4403 fprintf(stderr,"ERROR: NULL register\n");
4412 /*-----------------------------------------------------------------*/
4414 /*-----------------------------------------------------------------*/
4415 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4417 static void InsertpFlow(pCode *pc, pCode **pflow)
4420 PCFL(*pflow)->end = pc;
4422 if(!pc || !pc->next)
4425 *pflow = pic16_newpCodeFlow();
4426 pic16_pCodeInsertAfter(pc, *pflow);
4429 /*-----------------------------------------------------------------*/
4430 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4431 /* the flow blocks. */
4433 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4434 * point the instruction flow changes.
4436 /*-----------------------------------------------------------------*/
4437 void pic16_BuildFlow(pBlock *pb)
4440 pCode *last_pci=NULL;
4447 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4448 /* Insert a pCodeFlow object at the beginning of a pBlock */
4450 InsertpFlow(pb->pcHead, &pflow);
4452 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
4453 //pflow->next = pb->pcHead; /* Make the current head the next object */
4454 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4455 //pb->pcHead = pflow; /* Make the Flow object the head */
4458 for( pc = pic16_findNextInstruction(pb->pcHead);
4460 pc=pic16_findNextInstruction(pc)) {
4463 PCI(pc)->pcflow = PCFL(pflow);
4465 //fprintf(stderr," build: ");
4466 //pflow->print(stderr,pflow);
4468 if( PCI(pc)->isSkip) {
4470 /* The two instructions immediately following this one
4471 * mark the beginning of a new flow segment */
4473 while(pc && PCI(pc)->isSkip) {
4475 PCI(pc)->pcflow = PCFL(pflow);
4479 InsertpFlow(pc, &pflow);
4480 pc=pic16_findNextInstruction(pc->next);
4488 PCI(pc)->pcflow = PCFL(pflow);
4490 InsertpFlow(pc, &pflow);
4492 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
4494 InsertpFlow(pc, &pflow);
4497 } else if (checkLabel(pc)) {
4499 /* This instruction marks the beginning of a
4500 * new flow segment */
4505 /* If the previous pCode is not a flow object, then
4506 * insert a new flow object. (This check prevents
4507 * two consecutive flow objects from being insert in
4508 * the case where a skip instruction preceeds an
4509 * instruction containing a label.) */
4511 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4512 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4514 PCI(pc)->pcflow = PCFL(pflow);
4521 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4523 PCFL(pflow)->end = pb->pcTail;
4526 /*-------------------------------------------------------------------*/
4527 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4528 /* the flow blocks. */
4530 * unBuildFlow removes pCodeFlow objects from a pCode chain
4532 /*-----------------------------------------------------------------*/
4533 static void unBuildFlow(pBlock *pb)
4548 if(PCI(pc)->pcflow) {
4549 //free(PCI(pc)->pcflow);
4550 PCI(pc)->pcflow = NULL;
4553 } else if(isPCFL(pc) )
4562 /*-----------------------------------------------------------------*/
4563 /*-----------------------------------------------------------------*/
4564 static void dumpCond(int cond)
4567 static char *pcc_str[] = {
4582 int ncond = sizeof(pcc_str) / sizeof(char *);
4585 fprintf(stderr, "0x%04X\n",cond);
4587 for(i=0,j=1; i<ncond; i++, j<<=1)
4589 fprintf(stderr, " %s\n",pcc_str[i]);
4595 /*-----------------------------------------------------------------*/
4596 /*-----------------------------------------------------------------*/
4597 static void FlowStats(pCodeFlow *pcflow)
4605 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4607 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4610 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4615 fprintf(stderr, " FlowStats inCond: ");
4616 dumpCond(pcflow->inCond);
4617 fprintf(stderr, " FlowStats outCond: ");
4618 dumpCond(pcflow->outCond);
4622 /*-----------------------------------------------------------------*
4623 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4624 * if it affects the banking bits.
4626 * return: -1 == Banking bits are unaffected by this pCode.
4628 * return: > 0 == Banking bits are affected.
4630 * If the banking bits are affected, then the returned value describes
4631 * which bits are affected and how they're affected. The lower half
4632 * of the integer maps to the bits that are affected, the upper half
4633 * to whether they're set or cleared.
4635 *-----------------------------------------------------------------*/
4637 static int isBankInstruction(pCode *pc)
4645 if( PCI(pc)->op == POC_MOVLB ||
4646 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4647 bank = PCOL(pc)->lit;
4654 /*-----------------------------------------------------------------*/
4655 /*-----------------------------------------------------------------*/
4656 static void FillFlow(pCodeFlow *pcflow)
4665 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4667 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4670 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4677 isBankInstruction(pc);
4679 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4683 fprintf(stderr, " FillFlow - Bad end of flow\n");
4685 fprintf(stderr, " FillFlow - Ending flow with\n ");
4686 pc->print(stderr,pc);
4689 fprintf(stderr, " FillFlow inCond: ");
4690 dumpCond(pcflow->inCond);
4691 fprintf(stderr, " FillFlow outCond: ");
4692 dumpCond(pcflow->outCond);
4696 /*-----------------------------------------------------------------*/
4697 /*-----------------------------------------------------------------*/
4698 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4700 pCodeFlowLink *fromLink, *toLink;
4702 if(!from || !to || !to->pcflow || !from->pcflow)
4705 fromLink = pic16_newpCodeFlowLink(from->pcflow);
4706 toLink = pic16_newpCodeFlowLink(to->pcflow);
4708 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4709 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4713 /*-----------------------------------------------------------------*
4714 * void LinkFlow(pBlock *pb)
4716 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
4717 * non-branching segments. In LinkFlow, we determine the execution
4718 * order of these segments. For example, if one of the segments ends
4719 * with a skip, then we know that there are two possible flow segments
4720 * to which control may be passed.
4721 *-----------------------------------------------------------------*/
4722 static void LinkFlow(pBlock *pb)
4728 //fprintf(stderr,"linkflow \n");
4730 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4732 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4735 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4737 //fprintf(stderr," link: ");
4738 //pcflow->print(stderr,pcflow);
4740 //FillFlow(PCFL(pcflow));
4742 pc = PCFL(pcflow)->end;
4744 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4745 if(isPCI_SKIP(pc)) {
4746 //fprintf(stderr, "ends with skip\n");
4747 //pc->print(stderr,pc);
4748 pct=pic16_findNextInstruction(pc->next);
4749 LinkFlow_pCode(PCI(pc),PCI(pct));
4750 pct=pic16_findNextInstruction(pct->next);
4751 LinkFlow_pCode(PCI(pc),PCI(pct));
4755 if(isPCI_BRANCH(pc)) {
4756 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4758 //fprintf(stderr, "ends with branch\n ");
4759 //pc->print(stderr,pc);
4761 if(!(pcol && isPCOLAB(pcol))) {
4762 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4763 pc->print(stderr,pc);
4764 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4769 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4770 LinkFlow_pCode(PCI(pc),PCI(pct));
4772 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4773 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4774 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4780 //fprintf(stderr, "ends with non-branching instruction:\n");
4781 //pc->print(stderr,pc);
4783 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
4789 //fprintf(stderr, "ends with unknown\n");
4790 //pc->print(stderr,pc);
4794 //fprintf(stderr, "ends with nothing: ERROR\n");
4798 /*-----------------------------------------------------------------*/
4799 /*-----------------------------------------------------------------*/
4801 /*-----------------------------------------------------------------*/
4802 /*-----------------------------------------------------------------*/
4803 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
4809 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4812 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4818 /*-----------------------------------------------------------------*/
4819 /* BanksUsedFlow - Identify which banks are used in flow 2. */
4820 /*-----------------------------------------------------------------*/
4821 static void BanksUsedFlow2(pCode *pcflow)
4830 if(!isPCFL(pcflow)) {
4831 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4835 pc = pic16_findNextInstruction(pcflow->next);
4837 PCFL(pcflow)->lastBank = -1;
4839 while(pic16_isPCinFlow(pc,pcflow)) {
4841 int bank_selected = isBankInstruction(pc);
4843 //if(PCI(pc)->pcflow)
4844 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4846 if(bank_selected >= 0) {
4847 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4849 /* This instruction is modifying banking bits before accessing registers */
4851 PCFL(pcflow)->firstBank = -1;
4853 if(PCFL(pcflow)->lastBank == -1)
4854 PCFL(pcflow)->lastBank = 0;
4856 bank = 1 << bank_selected;
4857 PCFL(pcflow)->lastBank |= bank;
4861 reg = pic16_getRegFromInstruction(pc);
4863 if(reg && !pic16_isREGinBank(reg, bank)) {
4864 int allbanks = pic16_REGallBanks(reg);
4866 PCFL(pcflow)->firstBank = allbanks;
4868 PCFL(pcflow)->lastBank = allbanks;
4875 pc = pic16_findNextInstruction(pc->next);
4878 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4879 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4884 /*-----------------------------------------------------------------*/
4885 /*-----------------------------------------------------------------*/
4886 static void BanksUsedFlow(pBlock *pb)
4891 //pb->pcHead->print(stderr, pb->pcHead);
4893 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4894 //pcflow->print(stderr,pcflow);
4896 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4898 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4900 BanksUsedFlow2(pcflow);
4906 /*-----------------------------------------------------------------*/
4907 /*-----------------------------------------------------------------*/
4908 static void insertBankSwitch(int position, pCode *pc, int bsr)
4915 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
4918 /* insert the bank switch after this pc instruction */
4919 pCode *pcnext = pic16_findNextInstruction(pc);
4920 pic16_pCodeInsertAfter(pc, new_pc);
4925 pic16_pCodeInsertAfter(pc->prev, new_pc);
4927 /* Move the label, if there is one */
4929 if(PCI(pc)->label) {
4930 PCI(new_pc)->label = PCI(pc)->label;
4931 PCI(pc)->label = NULL;
4934 /* The new instruction has the same pcflow block */
4935 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
4938 /*-----------------------------------------------------------------*/
4939 /*-----------------------------------------------------------------*/
4940 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4951 pc = pic16_findNextInstruction(pcfl->pc.next);
4953 while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
4955 reg = pic16_getRegFromInstruction(pc);
4958 fprintf(stderr, " %s ",reg->name);
4959 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4964 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
4965 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4968 /* Examine the instruction before this one to make sure it is
4969 * not a skip type instruction */
4970 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4972 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4975 reg_bank = (reg) ? REG_BANK(reg) : 0;
4978 if (cur_bank != reg_bank) {
4979 //fprintf(stderr, "Cool! can switch banks\n");
4980 cur_bank = reg_bank;
4981 insertBankSwitch(0, pc, cur_bank);
4985 //fprintf(stderr, "Bummer can't switch banks\n");
4991 pc = pic16_findNextInstruction(pc->next);
4995 if(pcprev && cur_bank) {
4996 /* Brute force - make sure that we point to bank 0 at the
4997 * end of each flow block */
4998 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
4999 pic16_pCodeInsertAfter(pcprev, new_pc);
5001 //fprintf(stderr, "Brute force switch\n");
5006 /*-----------------------------------------------------------------*/
5007 /*int compareBankFlow - compare the banking requirements between */
5009 /*-----------------------------------------------------------------*/
5010 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5013 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5016 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5019 if(pcflow->firstBank == -1)
5023 if(pcflowLink->pcflow->firstBank == -1) {
5024 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5025 pcflowLink->pcflow->to :
5026 pcflowLink->pcflow->from);
5027 return compareBankFlow(pcflow, pctl, toORfrom);
5031 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5034 pcflowLink->bank_conflict++;
5035 pcflowLink->pcflow->FromConflicts++;
5036 pcflow->ToConflicts++;
5039 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5042 pcflowLink->bank_conflict++;
5043 pcflowLink->pcflow->ToConflicts++;
5044 pcflow->FromConflicts++;
5048 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5049 pcflowLink->pcflow->pc.seq,
5050 pcflowLink->pcflow->FromConflicts,
5051 pcflowLink->pcflow->ToConflicts);
5056 /*-----------------------------------------------------------------*/
5057 /*-----------------------------------------------------------------*/
5058 static void FixBankFlow(pBlock *pb)
5062 pCodeFlowLink *pcfl;
5064 pCode *pcflow_max_To=NULL;
5065 pCode *pcflow_max_From=NULL;
5066 int max_ToConflicts=0;
5067 int max_FromConflicts=0;
5069 //fprintf(stderr,"Fix Bank flow \n");
5070 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5074 First loop through all of the flow objects in this pcode block
5075 and fix the ones that have banking conflicts between the
5079 //fprintf(stderr, "FixBankFlow - Phase 1\n");
5081 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5083 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5085 if(!isPCFL(pcflow)) {
5086 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5090 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
5091 PCFL(pcflow)->firstBank >= 0 &&
5092 PCFL(pcflow)->lastBank >= 0 ) {
5094 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5095 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5097 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5098 BanksUsedFlow2(pcflow);
5103 //fprintf(stderr, "FixBankFlow - Phase 2\n");
5105 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5107 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5112 if(!isPCFL(pcflow)) {
5113 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5117 PCFL(pcflow)->FromConflicts = 0;
5118 PCFL(pcflow)->ToConflicts = 0;
5123 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5124 pcfl = setFirstItem(PCFL(pcflow)->from);
5127 pc = PCODE(pcfl->pcflow);
5130 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5131 pc->print(stderr,pc);
5134 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5137 pcfl=setNextItem(PCFL(pcflow)->from);
5140 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5141 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5143 FixRegisterBankingInFlow(PCFL(pcflow),0);
5144 BanksUsedFlow2(pcflow);
5146 continue; /* Don't need to check the flow from here - it's already been fixed */
5153 pcfl = setFirstItem(PCFL(pcflow)->to);
5156 pc = PCODE(pcfl->pcflow);
5158 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5159 pc->print(stderr,pc);
5162 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5165 pcfl=setNextItem(PCFL(pcflow)->to);
5168 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5169 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5171 FixRegisterBankingInFlow(PCFL(pcflow),0);
5172 BanksUsedFlow2(pcflow);
5177 Loop through the flow objects again and find the ones with the
5181 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5183 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5185 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5186 pcflow_max_To = pcflow;
5188 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5189 pcflow_max_From = pcflow;
5193 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5194 PCFL(pcflow_max_To)->pc.seq,
5195 PCFL(pcflow_max_To)->ToConflicts);
5198 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5199 PCFL(pcflow_max_From)->pc.seq,
5200 PCFL(pcflow_max_From)->FromConflicts);
5204 /*-----------------------------------------------------------------*/
5205 /*-----------------------------------------------------------------*/
5206 static void DumpFlow(pBlock *pb)
5210 pCodeFlowLink *pcfl;
5213 fprintf(stderr,"Dump flow \n");
5214 pb->pcHead->print(stderr, pb->pcHead);
5216 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5217 pcflow->print(stderr,pcflow);
5219 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5221 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5223 if(!isPCFL(pcflow)) {
5224 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5227 fprintf(stderr,"dumping: ");
5228 pcflow->print(stderr,pcflow);
5229 FlowStats(PCFL(pcflow));
5231 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5233 pc = PCODE(pcfl->pcflow);
5235 fprintf(stderr, " from seq %d:\n",pc->seq);
5237 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5238 pc->print(stderr,pc);
5243 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5245 pc = PCODE(pcfl->pcflow);
5247 fprintf(stderr, " to seq %d:\n",pc->seq);
5249 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5250 pc->print(stderr,pc);
5259 /*-----------------------------------------------------------------*/
5260 /*-----------------------------------------------------------------*/
5261 static int OptimizepBlock(pBlock *pb)
5266 if(!pb || !peepOptimizing)
5269 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5271 for(pc = pb->pcHead; pc; pc = pc->next)
5272 matches += pic16_pCodePeepMatchRule(pc);
5275 pc = pic16_findNextInstruction(pb->pcHead);
5283 if(pic16_pCodePeepMatchRule(pc)) {
5288 pc = pic16_findNextInstruction(pcprev->next);
5290 pc = pic16_findNextInstruction(pb->pcHead);
5292 pc = pic16_findNextInstruction(pc->next);
5296 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5301 /*-----------------------------------------------------------------*/
5302 /*-----------------------------------------------------------------*/
5303 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5307 for(pc = pcs; pc; pc = pc->next) {
5309 if((pc->type == PC_OPCODE) &&
5311 (PCI(pc)->pcop->type == PO_LABEL) &&
5312 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5320 /*-----------------------------------------------------------------*/
5321 /*-----------------------------------------------------------------*/
5322 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5329 (PCI(pc)->pcop->type == PO_LABEL)) {
5331 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5333 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5335 free(pcol->pcop.name);
5337 /* If the key is negative, then we (probably) have a label to
5338 * a function and the name is already defined */
5341 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5345 //sprintf(buffer,"_%05d_DS_",pcl->key);
5347 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5349 pcol->pcop.name = Safe_strdup(s);
5350 pcol->key = pcl->key;
5351 //pc->print(stderr,pc);
5358 /*-----------------------------------------------------------------*/
5359 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5360 /* pCode chain if they're not used. */
5361 /*-----------------------------------------------------------------*/
5362 static void pBlockRemoveUnusedLabels(pBlock *pb)
5364 pCode *pc; pCodeLabel *pcl;
5369 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5371 pBranch *pbr = PCI(pc)->label;
5372 if(pbr && pbr->next) {
5373 pCode *pcd = pb->pcHead;
5375 //fprintf(stderr, "multiple labels\n");
5376 //pc->print(stderr,pc);
5381 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5382 //fprintf(stderr,"Used by:\n");
5383 //pcd->print(stderr,pcd);
5385 exchangeLabels(PCL(pbr->pc),pcd);
5394 for(pc = pb->pcHead; pc; pc = pc->next) {
5396 if(isPCL(pc)) // pc->type == PC_LABEL)
5398 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5399 pcl = PCL(PCI(pc)->label->pc);
5402 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5404 /* This pCode is a label, so search the pBlock to see if anyone
5407 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5408 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5409 /* Couldn't find an instruction that refers to this label
5410 * So, unlink the pCode label from it's pCode chain
5411 * and destroy the label */
5412 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5414 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5415 if(pc->type == PC_LABEL) {
5416 pic16_unlinkpCode(pc);
5417 pCodeLabelDestruct(pc);
5419 unlinkpCodeFromBranch(pc, PCODE(pcl));
5420 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5431 /*-----------------------------------------------------------------*/
5432 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5433 /* chain and put them into pBranches that are */
5434 /* associated with the appropriate pCode */
5436 /*-----------------------------------------------------------------*/
5437 void pic16_pBlockMergeLabels(pBlock *pb)
5440 pCode *pc, *pcnext=NULL;
5445 /* First, Try to remove any unused labels */
5446 //pBlockRemoveUnusedLabels(pb);
5448 /* Now loop through the pBlock and merge the labels with the opcodes */
5451 // for(pc = pb->pcHead; pc; pc = pc->next) {
5454 pCode *pcn = pc->next;
5456 if(pc->type == PC_LABEL) {
5458 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5459 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5460 if((pcnext = pic16_findNextInstruction(pc) )) {
5462 // Unlink the pCode label from it's pCode chain
5463 pic16_unlinkpCode(pc);
5465 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5466 // And link it into the instruction's pBranch labels. (Note, since
5467 // it's possible to have multiple labels associated with one instruction
5468 // we must provide a means to accomodate the additional labels. Thus
5469 // the labels are placed into the singly-linked list "label" as
5470 // opposed to being a single member of the pCodeInstruction.)
5472 //_ALLOC(pbr,sizeof(pBranch));
5473 pbr = Safe_calloc(1,sizeof(pBranch));
5477 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5480 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5482 } else if(pc->type == PC_CSOURCE) {
5484 /* merge the source line symbolic info into the next instruction */
5485 if((pcnext = pic16_findNextInstruction(pc) )) {
5487 // Unlink the pCode label from it's pCode chain
5488 pic16_unlinkpCode(pc);
5489 PCI(pcnext)->cline = PCCS(pc);
5490 //fprintf(stderr, "merging CSRC\n");
5491 //genericPrint(stderr,pcnext);
5497 pBlockRemoveUnusedLabels(pb);
5501 /*-----------------------------------------------------------------*/
5502 /*-----------------------------------------------------------------*/
5503 static int OptimizepCode(char dbName)
5505 #define MAX_PASSES 4
5514 DFPRINTF((stderr," Optimizing pCode\n"));
5518 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5519 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5520 matches += OptimizepBlock(pb);
5523 while(matches && ++passes < MAX_PASSES);
5528 /*-----------------------------------------------------------------*/
5529 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5530 /*-----------------------------------------------------------------*/
5532 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5536 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5538 if( !( (pcop->type == PO_LABEL) ||
5539 (pcop->type == PO_LITERAL) ||
5540 (pcop->type == PO_STR) ))
5541 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5549 /*-----------------------------------------------------------------*/
5550 /*-----------------------------------------------------------------*/
5551 int InstructionRegBank(pCode *pc)
5555 if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5558 return REG_BANK(reg);
5563 /*-----------------------------------------------------------------*/
5564 /*-----------------------------------------------------------------*/
5565 static void FixRegisterBanking(pBlock *pb)
5576 //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5577 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5580 /* loop through all of the flow blocks with in one pblock */
5582 //fprintf(stderr,"Register banking\n");
5585 /* at this point, pc should point to a PC_FLOW object */
5588 /* for each flow block, determine the register banking
5593 //genericPrint(stderr, pc);
5595 reg = pic16_getRegFromInstruction(pc);
5598 fprintf(stderr, " %s ",reg->name);
5599 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
5600 reg->address,REG_BANK(reg),reg->isBitField);
5605 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
5606 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5610 /* Examine the instruction before this one to make sure it is
5611 * not a skip type instruction */
5612 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5614 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5617 reg_bank = (reg) ? REG_BANK(reg) : 0;
5619 if (cur_bank != reg_bank) {
5620 cur_bank = reg_bank;
5621 insertBankSwitch(0, pc, cur_bank);
5625 //fprintf(stderr, "Bummer can't switch banks\n");
5635 // } while(pc && !(isPCFL(pc)));
5640 if(pcprev && cur_bank) {
5642 int pos = 1; /* Assume that the bank switch instruction(s)
5643 * are inserted after this instruction */
5645 if((PCI(pcprev)->op == POC_RETLW) ||
5646 (PCI(pcprev)->op == POC_RETURN) ||
5647 (PCI(pcprev)->op == POC_RETFIE)) {
5649 /* oops, a RETURN - we need to switch banks *before* the RETURN */
5655 /* Brute force - make sure that we point to bank 0 at the
5656 * end of each flow block */
5658 insertBankSwitch(pos, pcprev, 0);
5660 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5661 pic16_pCodeInsertAfter(pcprev, new_pc);
5664 //fprintf(stderr, "Brute force switch\n");
5673 if(reg && REG_BANK(reg)!=cur_bank) {
5674 //fprintf(stderr,"need to switch banks\n");
5675 /* Examine the instruction before this one to make sure it is
5676 * not a skip type instruction */
5677 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5678 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5679 int b = cur_bank ^ REG_BANK(reg);
5681 cur_bank = REG_BANK(reg);
5687 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5690 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5691 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5695 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5696 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5698 insertBankSwitch(0, pc, -1, -1);
5707 static void pBlockDestruct(pBlock *pb)
5718 /*-----------------------------------------------------------------*/
5719 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5720 /* name dbName and combine them */
5721 /* into one block */
5722 /*-----------------------------------------------------------------*/
5723 static void mergepBlocks(char dbName)
5726 pBlock *pb, *pbmerged = NULL,*pbn;
5728 pb = the_pFile->pbHead;
5730 //fprintf(stderr," merging blocks named %c\n",dbName);
5734 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5735 if( getpBlock_dbName(pb) == dbName) {
5737 //fprintf(stderr," merged block %c\n",dbName);
5742 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
5743 /* pic16_addpCode2pBlock doesn't handle the tail: */
5744 pbmerged->pcTail = pb->pcTail;
5746 pb->prev->next = pbn;
5748 pbn->prev = pb->prev;
5753 //pic16_printpBlock(stderr, pbmerged);
5760 /*-----------------------------------------------------------------*/
5761 /* AnalyzeFlow - Examine the flow of the code and optimize */
5763 /* level 0 == minimal optimization */
5764 /* optimize registers that are used only by two instructions */
5765 /* level 1 == maximal optimization */
5766 /* optimize by looking at pairs of instructions that use the */
5768 /*-----------------------------------------------------------------*/
5770 static void AnalyzeFlow(int level)
5772 static int times_called=0;
5780 /* if this is not the first time this function has been called,
5781 then clean up old flow information */
5782 if(times_called++) {
5783 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5786 pic16_RegsUnMapLiveRanges();
5792 /* Phase 2 - Flow Analysis - Register Banking
5794 * In this phase, the individual flow blocks are examined
5795 * and register banking is fixed.
5798 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5799 //FixRegisterBanking(pb);
5801 /* Phase 2 - Flow Analysis
5803 * In this phase, the pCode is partition into pCodeFlow
5804 * blocks. The flow blocks mark the points where a continuous
5805 * stream of instructions changes flow (e.g. because of
5806 * a call or goto or whatever).
5809 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5810 pic16_BuildFlow(pb);
5813 /* Phase 2 - Flow Analysis - linking flow blocks
5815 * In this phase, the individual flow blocks are examined
5816 * to determine their order of excution.
5819 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5822 /* Phase 3 - Flow Analysis - Flow Tree
5824 * In this phase, the individual flow blocks are examined
5825 * to determine their order of excution.
5828 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5829 pic16_BuildFlowTree(pb);
5832 /* Phase x - Flow Analysis - Used Banks
5834 * In this phase, the individual flow blocks are examined
5835 * to determine the Register Banks they use
5838 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5842 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5843 pic16_pCodeRegMapLiveRanges(pb);
5845 pic16_RemoveUnusedRegisters();
5847 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5848 pic16_pCodeRegOptimizeRegUsage(level);
5854 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5858 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5860 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5861 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5862 pcflow = pcflow->next) {
5864 FillFlow(PCFL(pcflow));
5869 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5871 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5872 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5873 pcflow = pcflow->next) {
5875 FlowStats(PCFL(pcflow));
5881 /*-----------------------------------------------------------------*/
5882 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
5883 /* assigned to the registers. */
5885 /*-----------------------------------------------------------------*/
5887 void pic16_AnalyzeBanking(void)
5891 if(!pic16_picIsInitialized()) {
5892 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5893 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5894 fprintf(stderr,"support/scripts/inc2h.pl\n");
5895 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5900 /* Phase x - Flow Analysis - Used Banks
5902 * In this phase, the individual flow blocks are examined
5903 * to determine the Register Banks they use
5909 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5911 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5912 FixRegisterBanking(pb);
5916 /*-----------------------------------------------------------------*/
5917 /* buildCallTree - Look at the flow and extract all of the calls. */
5918 /*-----------------------------------------------------------------*/
5919 static set *register_usage(pBlock *pb);
5921 static void buildCallTree(void )
5932 /* Now build the call tree.
5933 First we examine all of the pCodes for functions.
5934 Keep in mind that the function boundaries coincide
5935 with pBlock boundaries.
5937 The algorithm goes something like this:
5938 We have two nested loops. The outer loop iterates
5939 through all of the pBlocks/functions. The inner
5940 loop iterates through all of the pCodes for
5941 a given pBlock. When we begin iterating through
5942 a pBlock, the variable pc_fstart, pCode of the start
5943 of a function, is cleared. We then search for pCodes
5944 of type PC_FUNCTION. When one is encountered, we
5945 initialize pc_fstart to this and at the same time
5946 associate a new pBranch object that signifies a
5947 branch entry. If a return is found, then this signifies
5948 a function exit point. We'll link the pCodes of these
5949 returns to the matching pc_fstart.
5951 When we're done, a doubly linked list of pBranches
5952 will exist. The head of this list is stored in
5953 `the_pFile', which is the meta structure for all
5954 of the pCode. Look at the pic16_printCallTree function
5955 on how the pBranches are linked together.
5958 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5959 pCode *pc_fstart=NULL;
5960 for(pc = pb->pcHead; pc; pc = pc->next) {
5962 if (PCF(pc)->fname) {
5964 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5965 //fprintf(stderr," found main \n");
5966 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5970 pbr = Safe_calloc(1,sizeof(pBranch));
5971 pbr->pc = pc_fstart = pc;
5974 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
5976 // Here's a better way of doing the same:
5977 addSet(&pb->function_entries, pc);
5980 // Found an exit point in a function, e.g. return
5981 // (Note, there may be more than one return per function)
5983 pBranchLink(PCF(pc_fstart), PCF(pc));
5985 addSet(&pb->function_exits, pc);
5987 } else if(isCALL(pc)) {
5988 addSet(&pb->function_calls,pc);
5993 /* Re-allocate the registers so that there are no collisions
5994 * between local variables when one function call another */
5997 // pic16_deallocateAllRegs();
5999 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6006 /*-----------------------------------------------------------------*/
6007 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6008 /* all of the logical connections. */
6010 /* Essentially what's done here is that the pCode flow is */
6012 /*-----------------------------------------------------------------*/
6014 void pic16_AnalyzepCode(char dbName)
6025 /* Phase 1 - Register allocation and peep hole optimization
6027 * The first part of the analysis is to determine the registers
6028 * that are used in the pCode. Once that is done, the peep rules
6029 * are applied to the code. We continue to loop until no more
6030 * peep rule optimizations are found (or until we exceed the
6031 * MAX_PASSES threshold).
6033 * When done, the required registers will be determined.
6039 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6040 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6042 /* First, merge the labels with the instructions */
6043 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6044 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6046 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6047 //fprintf(stderr," analyze and merging block %c\n",dbName);
6048 pic16_pBlockMergeLabels(pb);
6051 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6055 changes = OptimizepCode(dbName);
6057 } while(changes && (i++ < MAX_PASSES));
6062 /*-----------------------------------------------------------------*/
6063 /* ispCodeFunction - returns true if *pc is the pCode of a */
6065 /*-----------------------------------------------------------------*/
6066 static bool ispCodeFunction(pCode *pc)
6069 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6075 /*-----------------------------------------------------------------*/
6076 /* findFunction - Search for a function by name (given the name) */
6077 /* in the set of all functions that are in a pBlock */
6078 /* (note - I expect this to change because I'm planning to limit */
6079 /* pBlock's to just one function declaration */
6080 /*-----------------------------------------------------------------*/
6081 static pCode *findFunction(char *fname)
6088 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6090 pc = setFirstItem(pb->function_entries);
6093 if((pc->type == PC_FUNCTION) &&
6095 (strcmp(fname, PCF(pc)->fname)==0))
6098 pc = setNextItem(pb->function_entries);
6106 static void MarkUsedRegisters(set *regset)
6111 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6112 r2 = pic16_regWithIdx(r1->rIdx);
6118 static void pBlockStats(FILE *of, pBlock *pb)
6124 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6126 // for now just print the first element of each set
6127 pc = setFirstItem(pb->function_entries);
6129 fprintf(of,";entry: ");
6132 pc = setFirstItem(pb->function_exits);
6134 fprintf(of,";has an exit\n");
6138 pc = setFirstItem(pb->function_calls);
6140 fprintf(of,";functions called:\n");
6143 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6144 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6146 pc = setNextItem(pb->function_calls);
6150 r = setFirstItem(pb->tregisters);
6152 int n = elementsInSet(pb->tregisters);
6154 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6157 fprintf(of,"; %s\n",r->name);
6158 r = setNextItem(pb->tregisters);
6163 /*-----------------------------------------------------------------*/
6164 /*-----------------------------------------------------------------*/
6166 static void sequencepCode(void)
6172 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6174 pb->seq = GpCodeSequenceNumber+1;
6176 for( pc = pb->pcHead; pc; pc = pc->next)
6177 pc->seq = ++GpCodeSequenceNumber;
6183 /*-----------------------------------------------------------------*/
6184 /*-----------------------------------------------------------------*/
6185 static set *register_usage(pBlock *pb)
6188 set *registers=NULL;
6189 set *registersInCallPath = NULL;
6191 /* check recursion */
6193 pc = setFirstItem(pb->function_entries);
6200 if(pc->type != PC_FUNCTION)
6201 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6203 pc = setFirstItem(pb->function_calls);
6204 for( ; pc; pc = setNextItem(pb->function_calls)) {
6206 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6207 char *dest = pic16_get_op_from_instruction(PCI(pc));
6209 pcn = findFunction(dest);
6211 registersInCallPath = register_usage(pcn->pb);
6213 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6218 pBlockStats(stderr,pb); // debug
6221 // Mark the registers in this block as used.
6223 MarkUsedRegisters(pb->tregisters);
6224 if(registersInCallPath) {
6225 /* registers were used in the functions this pBlock has called */
6226 /* so now, we need to see if these collide with the ones we are */
6229 regs *r1,*r2, *newreg;
6231 DFPRINTF((stderr,"comparing registers\n"));
6233 r1 = setFirstItem(registersInCallPath);
6236 r2 = setFirstItem(pb->tregisters);
6238 while(r2 && (r1->type != REG_STK)) {
6240 if(r2->rIdx == r1->rIdx) {
6241 newreg = pic16_findFreeReg(REG_GPR);
6245 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6249 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6250 r1->rIdx, newreg->rIdx));
6251 r2->rIdx = newreg->rIdx;
6252 //if(r2->name) free(r2->name);
6254 r2->name = Safe_strdup(newreg->name);
6258 newreg->wasUsed = 1;
6260 r2 = setNextItem(pb->tregisters);
6263 r1 = setNextItem(registersInCallPath);
6266 /* Collisions have been resolved. Now free the registers in the call path */
6267 r1 = setFirstItem(registersInCallPath);
6269 if(r1->type != REG_STK) {
6270 newreg = pic16_regWithIdx(r1->rIdx);
6273 r1 = setNextItem(registersInCallPath);
6277 // MarkUsedRegisters(pb->registers);
6279 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6282 DFPRINTF((stderr,"returning regs\n"));
6284 DFPRINTF((stderr,"not returning regs\n"));
6286 DFPRINTF((stderr,"pBlock after register optim.\n"));
6287 pBlockStats(stderr,pb); // debug
6293 /*-----------------------------------------------------------------*/
6294 /* pct2 - writes the call tree to a file */
6296 /*-----------------------------------------------------------------*/
6297 static void pct2(FILE *of,pBlock *pb,int indent)
6301 // set *registersInCallPath = NULL;
6307 return; //recursion ?
6309 pc = setFirstItem(pb->function_entries);
6316 for(i=0;i<indent;i++) // Indentation
6319 if(pc->type == PC_FUNCTION)
6320 fprintf(of,"%s\n",PCF(pc)->fname);
6325 pc = setFirstItem(pb->function_calls);
6326 for( ; pc; pc = setNextItem(pb->function_calls)) {
6328 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6329 char *dest = pic16_get_op_from_instruction(PCI(pc));
6331 pcn = findFunction(dest);
6333 pct2(of,pcn->pb,indent+1);
6335 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6343 /*-----------------------------------------------------------------*/
6344 /* pic16_printCallTree - writes the call tree to a file */
6346 /*-----------------------------------------------------------------*/
6348 void pic16_printCallTree(FILE *of)
6360 fprintf(of, "\npBlock statistics\n");
6361 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6366 fprintf(of,"Call Tree\n");
6367 pbr = the_pFile->functions;
6371 if(!ispCodeFunction(pc))
6372 fprintf(of,"bug in call tree");
6375 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6377 while(pc->next && !ispCodeFunction(pc->next)) {
6379 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6380 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6388 fprintf(of,"\n**************\n\na better call tree\n");
6389 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6394 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6395 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6401 /*-----------------------------------------------------------------*/
6403 /*-----------------------------------------------------------------*/
6405 static void InlineFunction(pBlock *pb)
6413 pc = setFirstItem(pb->function_calls);
6415 for( ; pc; pc = setNextItem(pb->function_calls)) {
6418 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6424 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6426 //fprintf(stderr,"Cool can inline:\n");
6427 //pcn->print(stderr,pcn);
6429 //fprintf(stderr,"recursive call Inline\n");
6430 InlineFunction(pcn->pb);
6431 //fprintf(stderr,"return from recursive call Inline\n");
6434 At this point, *pc points to a CALL mnemonic, and
6435 *pcn points to the function that is being called.
6437 To in-line this call, we need to remove the CALL
6438 and RETURN(s), and link the function pCode in with
6444 /* Remove the CALL */
6448 /* remove callee pBlock from the pBlock linked list */
6449 removepBlock(pcn->pb);
6457 /* Remove the Function pCode */
6458 pct = pic16_findNextInstruction(pcn->next);
6460 /* Link the function with the callee */
6461 pc->next = pcn->next;
6462 pcn->next->prev = pc;
6464 /* Convert the function name into a label */
6466 pbr = Safe_calloc(1,sizeof(pBranch));
6467 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6469 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6470 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6472 /* turn all of the return's except the last into goto's */
6473 /* check case for 2 instruction pBlocks */
6474 pce = pic16_findNextInstruction(pcn->next);
6476 pCode *pce_next = pic16_findNextInstruction(pce->next);
6478 if(pce_next == NULL) {
6479 /* found the last return */
6480 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6482 //fprintf(stderr,"found last return\n");
6483 //pce->print(stderr,pce);
6484 pce->prev->next = pc_call->next;
6485 pc_call->next->prev = pce->prev;
6486 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6496 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6502 /*-----------------------------------------------------------------*/
6504 /*-----------------------------------------------------------------*/
6506 void pic16_InlinepCode(void)
6515 if(!functionInlining)
6518 /* Loop through all of the function definitions and count the
6519 * number of times each one is called */
6520 //fprintf(stderr,"inlining %d\n",__LINE__);
6522 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6524 pc = setFirstItem(pb->function_calls);
6526 for( ; pc; pc = setNextItem(pb->function_calls)) {
6529 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6530 if(pcn && isPCF(pcn)) {
6531 PCF(pcn)->ncalled++;
6534 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6539 //fprintf(stderr,"inlining %d\n",__LINE__);
6541 /* Now, Loop through the function definitions again, but this
6542 * time inline those functions that have only been called once. */
6544 InlineFunction(the_pFile->pbHead);
6545 //fprintf(stderr,"inlining %d\n",__LINE__);
6547 for(pb = the_pFile->pbHead; pb; pb = pb->next)