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 = 0; /* 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,int 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 /*-----------------------------------------------------------------*/
3337 static void pCodeReadCodeTable(void)
3341 fprintf(stderr, " %s\n",__FUNCTION__);
3343 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3345 pic16_addpBlock(pb);
3347 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3348 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3349 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3350 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3352 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3353 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3354 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3355 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3360 /*-----------------------------------------------------------------*/
3361 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3362 /*-----------------------------------------------------------------*/
3363 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3370 /* If this is the first pcode to be added to a block that
3371 * was initialized with a NULL pcode, then go ahead and
3372 * make this pcode the head and tail */
3373 pb->pcHead = pb->pcTail = pc;
3376 pb->pcTail->next = pc;
3378 pc->prev = pb->pcTail;
3385 /*-----------------------------------------------------------------*/
3386 /* pic16_addpBlock - place a pBlock into the pFile */
3387 /*-----------------------------------------------------------------*/
3388 void pic16_addpBlock(pBlock *pb)
3390 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3393 /* First time called, we'll pass through here. */
3394 //_ALLOC(the_pFile,sizeof(pFile));
3395 the_pFile = Safe_calloc(1,sizeof(pFile));
3396 the_pFile->pbHead = the_pFile->pbTail = pb;
3397 the_pFile->functions = NULL;
3401 the_pFile->pbTail->next = pb;
3402 pb->prev = the_pFile->pbTail;
3404 the_pFile->pbTail = pb;
3407 /*-----------------------------------------------------------------*/
3408 /* removepBlock - remove a pBlock from the pFile */
3409 /*-----------------------------------------------------------------*/
3410 static void removepBlock(pBlock *pb)
3418 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3420 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3423 if(pbs == the_pFile->pbHead)
3424 the_pFile->pbHead = pbs->next;
3426 if (pbs == the_pFile->pbTail)
3427 the_pFile->pbTail = pbs->prev;
3430 pbs->next->prev = pbs->prev;
3433 pbs->prev->next = pbs->next;
3440 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3444 /*-----------------------------------------------------------------*/
3445 /* printpCode - write the contents of a pCode to a file */
3446 /*-----------------------------------------------------------------*/
3447 static void printpCode(FILE *of, pCode *pc)
3458 fprintf(of,"warning - unable to print pCode\n");
3461 /*-----------------------------------------------------------------*/
3462 /* pic16_printpBlock - write the contents of a pBlock to a file */
3463 /*-----------------------------------------------------------------*/
3464 void pic16_printpBlock(FILE *of, pBlock *pb)
3474 for(pc = pb->pcHead; pc; pc = pc->next)
3479 /*-----------------------------------------------------------------*/
3481 /* pCode processing */
3485 /*-----------------------------------------------------------------*/
3487 void pic16_unlinkpCode(pCode *pc)
3493 fprintf(stderr,"Unlinking: ");
3494 printpCode(stderr, pc);
3497 pc->prev->next = pc->next;
3499 pc->next->prev = pc->prev;
3501 pc->prev = pc->next = NULL;
3505 /*-----------------------------------------------------------------*/
3506 /*-----------------------------------------------------------------*/
3508 static void genericDestruct(pCode *pc)
3511 pic16_unlinkpCode(pc);
3514 /* For instructions, tell the register (if there's one used)
3515 * that it's no longer needed */
3516 regs *reg = pic16_getRegFromInstruction(pc);
3518 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3521 /* Instead of deleting the memory used by this pCode, mark
3522 * the object as bad so that if there's a pointer to this pCode
3523 * dangling around somewhere then (hopefully) when the type is
3524 * checked we'll catch it.
3529 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3536 /*-----------------------------------------------------------------*/
3537 /*-----------------------------------------------------------------*/
3538 static void pBlockRegs(FILE *of, pBlock *pb)
3543 r = setFirstItem(pb->tregisters);
3545 r = setNextItem(pb->tregisters);
3550 /*-----------------------------------------------------------------*/
3551 /*-----------------------------------------------------------------*/
3552 char *pic16_get_op(pCodeOp *pcop,char *buffer, int size)
3557 int use_buffer = 1; // copy the string to the passed buffer pointer
3562 use_buffer = 0; // Don't bother copying the string to the buffer.
3566 switch(pcop->type) {
3570 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3573 return PCOR(pcop)->r->name;
3576 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3579 SAFE_snprintf(&buffer,&size,"%s",r->name);
3589 if(PCOI(pcop)->_const) {
3591 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3592 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3595 8 * PCOI(pcop)->offset );
3597 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3600 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3601 SAFE_snprintf(&s,&size,"(%s + %d)",
3603 PCOI(pcop)->index );
3605 if(PCOI(pcop)->offset)
3606 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3608 SAFE_snprintf(&s,&size,"%s",pcop->name);
3616 //size = sizeof(buffer);
3617 if( PCOR(pcop)->instance) {
3618 SAFE_snprintf(&s,&size,"(%s + %d)",
3620 PCOR(pcop)->instance );
3621 //fprintf(stderr,"PO_DIR %s\n",buffer);
3623 SAFE_snprintf(&s,&size,"%s",pcop->name);
3629 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3638 return "NO operand";
3642 /*-----------------------------------------------------------------*/
3643 /*-----------------------------------------------------------------*/
3644 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3648 return pic16_get_op(pcc->pcop,NULL,0);
3650 return ("ERROR Null: "__FUNCTION__);
3654 /*-----------------------------------------------------------------*/
3655 /*-----------------------------------------------------------------*/
3656 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3659 fprintf(of,"pcodeopprint- not implemented\n");
3662 /*-----------------------------------------------------------------*/
3663 /*-----------------------------------------------------------------*/
3664 static char *pCode2str(char *str, int size, pCode *pc)
3672 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3674 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3676 if(PCI(pc)->isBitInst) {
3677 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3678 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3679 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
3680 PCI(pc)->pcop->name ,
3681 PCI(pc)->pcop->name );
3683 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
3684 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3685 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3686 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3688 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3689 //PCI(pc)->pcop->t.bit );
3692 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3693 if( PCI(pc)->num_ops == 3)
3694 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3696 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3699 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3701 if( PCI(pc)->num_ops == 3)
3702 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3710 /* assuming that comment ends with a \n */
3711 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3715 /* assuming that inline code ends with a \n */
3716 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3720 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3723 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3726 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3729 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3732 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3736 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3743 /*-----------------------------------------------------------------*/
3744 /* genericPrint - the contents of a pCode to a file */
3745 /*-----------------------------------------------------------------*/
3746 static void genericPrint(FILE *of, pCode *pc)
3754 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3758 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3762 // If the opcode has a label, print that first
3764 pBranch *pbl = PCI(pc)->label;
3765 while(pbl && pbl->pc) {
3766 if(pbl->pc->type == PC_LABEL)
3767 pCodePrintLabel(of, pbl->pc);
3773 genericPrint(of,PCODE(PCI(pc)->cline));
3778 pCode2str(str, 256, pc);
3780 fprintf(of,"%s",str);
3783 if(pic16_debug_verbose) {
3784 fprintf(of, "\t;key=%03x",pc->seq);
3786 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3791 pBranch *dpb = pc->to; // debug
3793 switch ( dpb->pc->type) {
3795 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3798 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3801 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3804 fprintf(of, "\t;flow");
3818 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3819 if(PCW(pc)->pci.label)
3820 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3822 if(PCW(pc)->operand) {
3823 fprintf(of,";\toperand ");
3824 pCodeOpPrint(of,PCW(pc)->operand );
3829 if(pic16_debug_verbose) {
3830 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3831 if(PCFL(pc)->ancestor)
3832 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3839 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3843 fprintf(of,"unknown pCode type %d\n",pc->type);
3848 /*-----------------------------------------------------------------*/
3849 /* pCodePrintFunction - prints function begin/end */
3850 /*-----------------------------------------------------------------*/
3852 static void pCodePrintFunction(FILE *of, pCode *pc)
3858 if( ((pCodeFunction *)pc)->modname)
3859 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3861 if(PCF(pc)->fname) {
3862 pBranch *exits = PCF(pc)->to;
3864 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3867 exits = exits->next;
3870 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3873 if((PCF(pc)->from &&
3874 PCF(pc)->from->pc->type == PC_FUNCTION &&
3875 PCF(PCF(pc)->from->pc)->fname) )
3876 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3878 fprintf(of,"; exit point [can't find entry point]\n");
3881 /*-----------------------------------------------------------------*/
3882 /* pCodePrintLabel - prints label */
3883 /*-----------------------------------------------------------------*/
3885 static void pCodePrintLabel(FILE *of, pCode *pc)
3892 fprintf(of,"%s\n",PCL(pc)->label);
3893 else if (PCL(pc)->key >=0)
3894 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3896 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3899 /*-----------------------------------------------------------------*/
3900 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3901 /* remove it if it is found. */
3902 /*-----------------------------------------------------------------*/
3903 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3910 if(pcl->type == PC_OPCODE)
3911 b = PCI(pcl)->label;
3913 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3918 //fprintf (stderr, "%s \n",__FUNCTION__);
3919 //pcl->print(stderr,pcl);
3920 //pc->print(stderr,pc);
3923 //fprintf (stderr, "found label\n");
3927 bprev->next = b->next; /* Not first pCode in chain */
3931 PCI(pcl)->label = b->next; /* First pCode in chain */
3934 return; /* A label can't occur more than once */
3942 /*-----------------------------------------------------------------*/
3943 /*-----------------------------------------------------------------*/
3944 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
3963 /*-----------------------------------------------------------------*/
3964 /* pBranchLink - given two pcodes, this function will link them */
3965 /* together through their pBranches */
3966 /*-----------------------------------------------------------------*/
3967 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3971 // Declare a new branch object for the 'from' pCode.
3973 //_ALLOC(b,sizeof(pBranch));
3974 b = Safe_calloc(1,sizeof(pBranch));
3975 b->pc = PCODE(t); // The link to the 'to' pCode.
3978 f->to = pic16_pBranchAppend(f->to,b);
3980 // Now do the same for the 'to' pCode.
3982 //_ALLOC(b,sizeof(pBranch));
3983 b = Safe_calloc(1,sizeof(pBranch));
3987 t->from = pic16_pBranchAppend(t->from,b);
3992 /*-----------------------------------------------------------------*/
3993 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3995 /*-----------------------------------------------------------------*/
3996 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4009 /*-----------------------------------------------------------------*/
4010 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4011 /*-----------------------------------------------------------------*/
4012 static void pCodeUnlink(pCode *pc)
4017 if(!pc->prev || !pc->next) {
4018 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4022 /* first remove the pCode from the chain */
4023 pc->prev->next = pc->next;
4024 pc->next->prev = pc->prev;
4026 /* Now for the hard part... */
4028 /* Remove the branches */
4032 pc1 = pb1->pc; /* Get the pCode that branches to the
4033 * one we're unlinking */
4035 /* search for the link back to this pCode (the one we're
4037 if(pb2 = pBranchFind(pc1->to,pc)) {
4038 pb2->pc = pc->to->pc; // make the replacement
4040 /* if the pCode we're unlinking contains multiple 'to'
4041 * branches (e.g. this a skip instruction) then we need
4042 * to copy these extra branches to the chain. */
4044 pic16_pBranchAppend(pb2, pc->to->next);
4053 /*-----------------------------------------------------------------*/
4054 /*-----------------------------------------------------------------*/
4056 static void genericAnalyze(pCode *pc)
4066 // Go through the pCodes that are in pCode chain and link
4067 // them together through the pBranches. Note, the pCodes
4068 // are linked together as a contiguous stream like the
4069 // assembly source code lines. The linking here mimics this
4070 // except that comments are not linked in.
4072 pCode *npc = pc->next;
4074 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4075 pBranchLink(pc,npc);
4080 /* reached the end of the pcode chain without finding
4081 * an instruction we could link to. */
4085 fprintf(stderr,"analyze PC_FLOW\n");
4089 fprintf(stderr,,";A bad pCode is being used\n");
4095 /*-----------------------------------------------------------------*/
4096 /*-----------------------------------------------------------------*/
4097 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4101 if(pc->type == PC_LABEL) {
4102 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4105 if(pc->type == PC_OPCODE) {
4106 pbr = PCI(pc)->label;
4108 if(pbr->pc->type == PC_LABEL) {
4109 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4119 /*-----------------------------------------------------------------*/
4120 /*-----------------------------------------------------------------*/
4121 static int checkLabel(pCode *pc)
4125 if(pc && isPCI(pc)) {
4126 pbr = PCI(pc)->label;
4128 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4138 /*-----------------------------------------------------------------*/
4139 /* findLabelinpBlock - Search the pCode for a particular label */
4140 /*-----------------------------------------------------------------*/
4141 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4148 for(pc = pb->pcHead; pc; pc = pc->next)
4149 if(compareLabel(pc,pcop_label))
4155 /*-----------------------------------------------------------------*/
4156 /* findLabel - Search the pCode for a particular label */
4157 /*-----------------------------------------------------------------*/
4158 static pCode * findLabel(pCodeOpLabel *pcop_label)
4166 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4167 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4171 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4175 /*-----------------------------------------------------------------*/
4176 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4177 /* in the linked list */
4178 /*-----------------------------------------------------------------*/
4179 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4192 /*-----------------------------------------------------------------*/
4193 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4194 /* in the linked list */
4195 /*-----------------------------------------------------------------*/
4196 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4208 /*-----------------------------------------------------------------*/
4209 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4210 /* in the linked list */
4211 /*-----------------------------------------------------------------*/
4212 pCode * pic16_findNextInstruction(pCode *pci)
4217 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4221 fprintf(stderr,"pic16_findNextInstruction: ");
4222 printpCode(stderr, pc);
4227 //fprintf(stderr,"Couldn't find instruction\n");
4231 /*-----------------------------------------------------------------*/
4232 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4233 /* in the linked list */
4234 /*-----------------------------------------------------------------*/
4235 pCode * pic16_findPrevInstruction(pCode *pci)
4237 return findPrevpCode(pci, PC_OPCODE);
4240 /*-----------------------------------------------------------------*/
4241 /* findFunctionEnd - given a pCode find the end of the function */
4242 /* that contains it */
4243 /*-----------------------------------------------------------------*/
4244 static pCode * findFunctionEnd(pCode *pc)
4248 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4254 fprintf(stderr,"Couldn't find function end\n");
4259 /*-----------------------------------------------------------------*/
4260 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4261 /* instruction with which it is associated. */
4262 /*-----------------------------------------------------------------*/
4263 static void AnalyzeLabel(pCode *pc)
4272 static void AnalyzeGOTO(pCode *pc)
4275 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4279 static void AnalyzeSKIP(pCode *pc)
4282 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4283 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4287 static void AnalyzeRETURN(pCode *pc)
4290 // branch_link(pc,findFunctionEnd(pc->next));
4296 /*-----------------------------------------------------------------*/
4297 /*-----------------------------------------------------------------*/
4298 regs * pic16_getRegFromInstruction(pCode *pc)
4304 PCI(pc)->num_ops == 0 ||
4305 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4308 switch(PCI(pc)->pcop->type) {
4311 return PCOR(PCI(pc)->pcop)->r;
4313 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4317 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4318 return PCOR(PCI(pc)->pcop)->r;
4321 if(PCOI(PCI(pc)->pcop)->r)
4322 return (PCOI(PCI(pc)->pcop)->r);
4324 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4325 return pic16_dirregWithName(PCI(pc)->pcop->name);
4326 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4329 return PCOR(PCI(pc)->pcop)->r;
4332 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4333 return PCOR(PCI(pc)->pcop)->r;
4335 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4339 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4340 //genericPrint(stderr, pc);
4348 /*-----------------------------------------------------------------*/
4349 /*-----------------------------------------------------------------*/
4351 static void AnalyzepBlock(pBlock *pb)
4358 /* Find all of the registers used in this pBlock
4359 * by looking at each instruction and examining it's
4362 for(pc = pb->pcHead; pc; pc = pc->next) {
4364 /* Is this an instruction with operands? */
4365 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4367 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4369 /* Loop through all of the registers declared so far in
4370 this block and see if we find this one there */
4372 regs *r = setFirstItem(pb->tregisters);
4375 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4376 PCOR(PCI(pc)->pcop)->r = r;
4379 r = setNextItem(pb->tregisters);
4383 /* register wasn't found */
4384 //r = Safe_calloc(1, sizeof(regs));
4385 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4386 //addSet(&pb->tregisters, r);
4387 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4388 //PCOR(PCI(pc)->pcop)->r = r;
4389 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4391 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4394 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4395 if(PCOR(PCI(pc)->pcop)->r) {
4396 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4397 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4399 if(PCI(pc)->pcop->name)
4400 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4402 fprintf(stderr,"ERROR: NULL register\n");
4411 /*-----------------------------------------------------------------*/
4413 /*-----------------------------------------------------------------*/
4414 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4416 static void InsertpFlow(pCode *pc, pCode **pflow)
4419 PCFL(*pflow)->end = pc;
4421 if(!pc || !pc->next)
4424 *pflow = pic16_newpCodeFlow();
4425 pic16_pCodeInsertAfter(pc, *pflow);
4428 /*-----------------------------------------------------------------*/
4429 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4430 /* the flow blocks. */
4432 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4433 * point the instruction flow changes.
4435 /*-----------------------------------------------------------------*/
4436 void pic16_BuildFlow(pBlock *pb)
4439 pCode *last_pci=NULL;
4446 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4447 /* Insert a pCodeFlow object at the beginning of a pBlock */
4449 InsertpFlow(pb->pcHead, &pflow);
4451 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
4452 //pflow->next = pb->pcHead; /* Make the current head the next object */
4453 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4454 //pb->pcHead = pflow; /* Make the Flow object the head */
4457 for( pc = pic16_findNextInstruction(pb->pcHead);
4459 pc=pic16_findNextInstruction(pc)) {
4462 PCI(pc)->pcflow = PCFL(pflow);
4464 //fprintf(stderr," build: ");
4465 //pflow->print(stderr,pflow);
4467 if( PCI(pc)->isSkip) {
4469 /* The two instructions immediately following this one
4470 * mark the beginning of a new flow segment */
4472 while(pc && PCI(pc)->isSkip) {
4474 PCI(pc)->pcflow = PCFL(pflow);
4478 InsertpFlow(pc, &pflow);
4479 pc=pic16_findNextInstruction(pc->next);
4487 PCI(pc)->pcflow = PCFL(pflow);
4489 InsertpFlow(pc, &pflow);
4491 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
4493 InsertpFlow(pc, &pflow);
4496 } else if (checkLabel(pc)) {
4498 /* This instruction marks the beginning of a
4499 * new flow segment */
4504 /* If the previous pCode is not a flow object, then
4505 * insert a new flow object. (This check prevents
4506 * two consecutive flow objects from being insert in
4507 * the case where a skip instruction preceeds an
4508 * instruction containing a label.) */
4510 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4511 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4513 PCI(pc)->pcflow = PCFL(pflow);
4520 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4522 PCFL(pflow)->end = pb->pcTail;
4525 /*-------------------------------------------------------------------*/
4526 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4527 /* the flow blocks. */
4529 * unBuildFlow removes pCodeFlow objects from a pCode chain
4531 /*-----------------------------------------------------------------*/
4532 static void unBuildFlow(pBlock *pb)
4547 if(PCI(pc)->pcflow) {
4548 //free(PCI(pc)->pcflow);
4549 PCI(pc)->pcflow = NULL;
4552 } else if(isPCFL(pc) )
4561 /*-----------------------------------------------------------------*/
4562 /*-----------------------------------------------------------------*/
4563 static void dumpCond(int cond)
4566 static char *pcc_str[] = {
4581 int ncond = sizeof(pcc_str) / sizeof(char *);
4584 fprintf(stderr, "0x%04X\n",cond);
4586 for(i=0,j=1; i<ncond; i++, j<<=1)
4588 fprintf(stderr, " %s\n",pcc_str[i]);
4592 /*-----------------------------------------------------------------*/
4593 /*-----------------------------------------------------------------*/
4594 static void FlowStats(pCodeFlow *pcflow)
4602 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4604 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4607 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4612 fprintf(stderr, " FlowStats inCond: ");
4613 dumpCond(pcflow->inCond);
4614 fprintf(stderr, " FlowStats outCond: ");
4615 dumpCond(pcflow->outCond);
4619 /*-----------------------------------------------------------------*
4620 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4621 * if it affects the banking bits.
4623 * return: -1 == Banking bits are unaffected by this pCode.
4625 * return: > 0 == Banking bits are affected.
4627 * If the banking bits are affected, then the returned value describes
4628 * which bits are affected and how they're affected. The lower half
4629 * of the integer maps to the bits that are affected, the upper half
4630 * to whether they're set or cleared.
4632 *-----------------------------------------------------------------*/
4634 static int isBankInstruction(pCode *pc)
4642 if( PCI(pc)->op == POC_MOVLB ||
4643 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4644 bank = PCOL(pc)->lit;
4651 /*-----------------------------------------------------------------*/
4652 /*-----------------------------------------------------------------*/
4653 static void FillFlow(pCodeFlow *pcflow)
4662 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4664 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4667 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4674 isBankInstruction(pc);
4676 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4680 fprintf(stderr, " FillFlow - Bad end of flow\n");
4682 fprintf(stderr, " FillFlow - Ending flow with\n ");
4683 pc->print(stderr,pc);
4686 fprintf(stderr, " FillFlow inCond: ");
4687 dumpCond(pcflow->inCond);
4688 fprintf(stderr, " FillFlow outCond: ");
4689 dumpCond(pcflow->outCond);
4693 /*-----------------------------------------------------------------*/
4694 /*-----------------------------------------------------------------*/
4695 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4697 pCodeFlowLink *fromLink, *toLink;
4699 if(!from || !to || !to->pcflow || !from->pcflow)
4702 fromLink = pic16_newpCodeFlowLink(from->pcflow);
4703 toLink = pic16_newpCodeFlowLink(to->pcflow);
4705 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4706 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4710 /*-----------------------------------------------------------------*
4711 * void LinkFlow(pBlock *pb)
4713 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
4714 * non-branching segments. In LinkFlow, we determine the execution
4715 * order of these segments. For example, if one of the segments ends
4716 * with a skip, then we know that there are two possible flow segments
4717 * to which control may be passed.
4718 *-----------------------------------------------------------------*/
4719 static void LinkFlow(pBlock *pb)
4725 //fprintf(stderr,"linkflow \n");
4727 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4729 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4732 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4734 //fprintf(stderr," link: ");
4735 //pcflow->print(stderr,pcflow);
4737 //FillFlow(PCFL(pcflow));
4739 pc = PCFL(pcflow)->end;
4741 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4742 if(isPCI_SKIP(pc)) {
4743 //fprintf(stderr, "ends with skip\n");
4744 //pc->print(stderr,pc);
4745 pct=pic16_findNextInstruction(pc->next);
4746 LinkFlow_pCode(PCI(pc),PCI(pct));
4747 pct=pic16_findNextInstruction(pct->next);
4748 LinkFlow_pCode(PCI(pc),PCI(pct));
4752 if(isPCI_BRANCH(pc)) {
4753 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4755 //fprintf(stderr, "ends with branch\n ");
4756 //pc->print(stderr,pc);
4758 if(!(pcol && isPCOLAB(pcol))) {
4759 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4760 pc->print(stderr,pc);
4761 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4766 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4767 LinkFlow_pCode(PCI(pc),PCI(pct));
4769 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4770 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4771 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4777 //fprintf(stderr, "ends with non-branching instruction:\n");
4778 //pc->print(stderr,pc);
4780 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
4786 //fprintf(stderr, "ends with unknown\n");
4787 //pc->print(stderr,pc);
4791 //fprintf(stderr, "ends with nothing: ERROR\n");
4795 /*-----------------------------------------------------------------*/
4796 /*-----------------------------------------------------------------*/
4798 /*-----------------------------------------------------------------*/
4799 /*-----------------------------------------------------------------*/
4800 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
4806 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4809 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4815 /*-----------------------------------------------------------------*/
4816 /* BanksUsedFlow - Identify which banks are used in flow 2. */
4817 /*-----------------------------------------------------------------*/
4818 static void BanksUsedFlow2(pCode *pcflow)
4827 if(!isPCFL(pcflow)) {
4828 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4832 pc = pic16_findNextInstruction(pcflow->next);
4834 PCFL(pcflow)->lastBank = -1;
4836 while(pic16_isPCinFlow(pc,pcflow)) {
4838 int bank_selected = isBankInstruction(pc);
4840 //if(PCI(pc)->pcflow)
4841 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4843 if(bank_selected >= 0) {
4844 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4846 /* This instruction is modifying banking bits before accessing registers */
4848 PCFL(pcflow)->firstBank = -1;
4850 if(PCFL(pcflow)->lastBank == -1)
4851 PCFL(pcflow)->lastBank = 0;
4853 bank = 1 << bank_selected;
4854 PCFL(pcflow)->lastBank |= bank;
4858 reg = pic16_getRegFromInstruction(pc);
4860 if(reg && !pic16_isREGinBank(reg, bank)) {
4861 int allbanks = pic16_REGallBanks(reg);
4863 PCFL(pcflow)->firstBank = allbanks;
4865 PCFL(pcflow)->lastBank = allbanks;
4872 pc = pic16_findNextInstruction(pc->next);
4875 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4876 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4881 /*-----------------------------------------------------------------*/
4882 /*-----------------------------------------------------------------*/
4883 static void BanksUsedFlow(pBlock *pb)
4888 //pb->pcHead->print(stderr, pb->pcHead);
4890 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4891 //pcflow->print(stderr,pcflow);
4893 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4895 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4897 BanksUsedFlow2(pcflow);
4903 /*-----------------------------------------------------------------*/
4904 /*-----------------------------------------------------------------*/
4905 static void insertBankSwitch(int position, pCode *pc, int bsr)
4912 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
4915 /* insert the bank switch after this pc instruction */
4916 pCode *pcnext = pic16_findNextInstruction(pc);
4917 pic16_pCodeInsertAfter(pc, new_pc);
4922 pic16_pCodeInsertAfter(pc->prev, new_pc);
4924 /* Move the label, if there is one */
4926 if(PCI(pc)->label) {
4927 PCI(new_pc)->label = PCI(pc)->label;
4928 PCI(pc)->label = NULL;
4931 /* The new instruction has the same pcflow block */
4932 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
4935 /*-----------------------------------------------------------------*/
4936 /*-----------------------------------------------------------------*/
4937 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4948 pc = pic16_findNextInstruction(pcfl->pc.next);
4950 while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
4952 reg = pic16_getRegFromInstruction(pc);
4955 fprintf(stderr, " %s ",reg->name);
4956 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4961 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
4962 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4965 /* Examine the instruction before this one to make sure it is
4966 * not a skip type instruction */
4967 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4969 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4972 reg_bank = (reg) ? REG_BANK(reg) : 0;
4975 if (cur_bank != reg_bank) {
4976 //fprintf(stderr, "Cool! can switch banks\n");
4977 cur_bank = reg_bank;
4978 insertBankSwitch(0, pc, cur_bank);
4982 //fprintf(stderr, "Bummer can't switch banks\n");
4988 pc = pic16_findNextInstruction(pc->next);
4992 if(pcprev && cur_bank) {
4993 /* Brute force - make sure that we point to bank 0 at the
4994 * end of each flow block */
4995 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
4996 pic16_pCodeInsertAfter(pcprev, new_pc);
4998 //fprintf(stderr, "Brute force switch\n");
5003 /*-----------------------------------------------------------------*/
5004 /*int compareBankFlow - compare the banking requirements between */
5006 /*-----------------------------------------------------------------*/
5007 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5010 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5013 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5016 if(pcflow->firstBank == -1)
5020 if(pcflowLink->pcflow->firstBank == -1) {
5021 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5022 pcflowLink->pcflow->to :
5023 pcflowLink->pcflow->from);
5024 return compareBankFlow(pcflow, pctl, toORfrom);
5028 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5031 pcflowLink->bank_conflict++;
5032 pcflowLink->pcflow->FromConflicts++;
5033 pcflow->ToConflicts++;
5036 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5039 pcflowLink->bank_conflict++;
5040 pcflowLink->pcflow->ToConflicts++;
5041 pcflow->FromConflicts++;
5045 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5046 pcflowLink->pcflow->pc.seq,
5047 pcflowLink->pcflow->FromConflicts,
5048 pcflowLink->pcflow->ToConflicts);
5053 /*-----------------------------------------------------------------*/
5054 /*-----------------------------------------------------------------*/
5055 static void FixBankFlow(pBlock *pb)
5059 pCodeFlowLink *pcfl;
5061 pCode *pcflow_max_To=NULL;
5062 pCode *pcflow_max_From=NULL;
5063 int max_ToConflicts=0;
5064 int max_FromConflicts=0;
5066 //fprintf(stderr,"Fix Bank flow \n");
5067 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5071 First loop through all of the flow objects in this pcode block
5072 and fix the ones that have banking conflicts between the
5076 //fprintf(stderr, "FixBankFlow - Phase 1\n");
5078 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5080 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5082 if(!isPCFL(pcflow)) {
5083 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5087 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
5088 PCFL(pcflow)->firstBank >= 0 &&
5089 PCFL(pcflow)->lastBank >= 0 ) {
5091 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5092 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5094 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5095 BanksUsedFlow2(pcflow);
5100 //fprintf(stderr, "FixBankFlow - Phase 2\n");
5102 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5104 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5109 if(!isPCFL(pcflow)) {
5110 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5114 PCFL(pcflow)->FromConflicts = 0;
5115 PCFL(pcflow)->ToConflicts = 0;
5120 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5121 pcfl = setFirstItem(PCFL(pcflow)->from);
5124 pc = PCODE(pcfl->pcflow);
5127 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5128 pc->print(stderr,pc);
5131 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5134 pcfl=setNextItem(PCFL(pcflow)->from);
5137 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5138 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5140 FixRegisterBankingInFlow(PCFL(pcflow),0);
5141 BanksUsedFlow2(pcflow);
5143 continue; /* Don't need to check the flow from here - it's already been fixed */
5150 pcfl = setFirstItem(PCFL(pcflow)->to);
5153 pc = PCODE(pcfl->pcflow);
5155 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5156 pc->print(stderr,pc);
5159 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5162 pcfl=setNextItem(PCFL(pcflow)->to);
5165 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5166 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5168 FixRegisterBankingInFlow(PCFL(pcflow),0);
5169 BanksUsedFlow2(pcflow);
5174 Loop through the flow objects again and find the ones with the
5178 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5180 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5182 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5183 pcflow_max_To = pcflow;
5185 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5186 pcflow_max_From = pcflow;
5190 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5191 PCFL(pcflow_max_To)->pc.seq,
5192 PCFL(pcflow_max_To)->ToConflicts);
5195 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5196 PCFL(pcflow_max_From)->pc.seq,
5197 PCFL(pcflow_max_From)->FromConflicts);
5201 /*-----------------------------------------------------------------*/
5202 /*-----------------------------------------------------------------*/
5203 static void DumpFlow(pBlock *pb)
5207 pCodeFlowLink *pcfl;
5210 fprintf(stderr,"Dump flow \n");
5211 pb->pcHead->print(stderr, pb->pcHead);
5213 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5214 pcflow->print(stderr,pcflow);
5216 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5218 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5220 if(!isPCFL(pcflow)) {
5221 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5224 fprintf(stderr,"dumping: ");
5225 pcflow->print(stderr,pcflow);
5226 FlowStats(PCFL(pcflow));
5228 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5230 pc = PCODE(pcfl->pcflow);
5232 fprintf(stderr, " from seq %d:\n",pc->seq);
5234 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5235 pc->print(stderr,pc);
5240 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5242 pc = PCODE(pcfl->pcflow);
5244 fprintf(stderr, " to seq %d:\n",pc->seq);
5246 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5247 pc->print(stderr,pc);
5256 /*-----------------------------------------------------------------*/
5257 /*-----------------------------------------------------------------*/
5258 static int OptimizepBlock(pBlock *pb)
5263 if(!pb || !peepOptimizing)
5266 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5268 for(pc = pb->pcHead; pc; pc = pc->next)
5269 matches += pic16_pCodePeepMatchRule(pc);
5272 pc = pic16_findNextInstruction(pb->pcHead);
5280 if(pic16_pCodePeepMatchRule(pc)) {
5285 pc = pic16_findNextInstruction(pcprev->next);
5287 pc = pic16_findNextInstruction(pb->pcHead);
5289 pc = pic16_findNextInstruction(pc->next);
5293 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5298 /*-----------------------------------------------------------------*/
5299 /*-----------------------------------------------------------------*/
5300 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5304 for(pc = pcs; pc; pc = pc->next) {
5306 if((pc->type == PC_OPCODE) &&
5308 (PCI(pc)->pcop->type == PO_LABEL) &&
5309 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5317 /*-----------------------------------------------------------------*/
5318 /*-----------------------------------------------------------------*/
5319 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5326 (PCI(pc)->pcop->type == PO_LABEL)) {
5328 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5330 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5332 free(pcol->pcop.name);
5334 /* If the key is negative, then we (probably) have a label to
5335 * a function and the name is already defined */
5338 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5342 //sprintf(buffer,"_%05d_DS_",pcl->key);
5344 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5346 pcol->pcop.name = Safe_strdup(s);
5347 pcol->key = pcl->key;
5348 //pc->print(stderr,pc);
5355 /*-----------------------------------------------------------------*/
5356 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5357 /* pCode chain if they're not used. */
5358 /*-----------------------------------------------------------------*/
5359 static void pBlockRemoveUnusedLabels(pBlock *pb)
5361 pCode *pc; pCodeLabel *pcl;
5366 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5368 pBranch *pbr = PCI(pc)->label;
5369 if(pbr && pbr->next) {
5370 pCode *pcd = pb->pcHead;
5372 //fprintf(stderr, "multiple labels\n");
5373 //pc->print(stderr,pc);
5378 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5379 //fprintf(stderr,"Used by:\n");
5380 //pcd->print(stderr,pcd);
5382 exchangeLabels(PCL(pbr->pc),pcd);
5391 for(pc = pb->pcHead; pc; pc = pc->next) {
5393 if(isPCL(pc)) // pc->type == PC_LABEL)
5395 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5396 pcl = PCL(PCI(pc)->label->pc);
5399 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5401 /* This pCode is a label, so search the pBlock to see if anyone
5404 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5405 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5406 /* Couldn't find an instruction that refers to this label
5407 * So, unlink the pCode label from it's pCode chain
5408 * and destroy the label */
5409 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5411 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5412 if(pc->type == PC_LABEL) {
5413 pic16_unlinkpCode(pc);
5414 pCodeLabelDestruct(pc);
5416 unlinkpCodeFromBranch(pc, PCODE(pcl));
5417 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5428 /*-----------------------------------------------------------------*/
5429 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5430 /* chain and put them into pBranches that are */
5431 /* associated with the appropriate pCode */
5433 /*-----------------------------------------------------------------*/
5434 void pic16_pBlockMergeLabels(pBlock *pb)
5437 pCode *pc, *pcnext=NULL;
5442 /* First, Try to remove any unused labels */
5443 //pBlockRemoveUnusedLabels(pb);
5445 /* Now loop through the pBlock and merge the labels with the opcodes */
5448 // for(pc = pb->pcHead; pc; pc = pc->next) {
5451 pCode *pcn = pc->next;
5453 if(pc->type == PC_LABEL) {
5455 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5456 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5457 if((pcnext = pic16_findNextInstruction(pc) )) {
5459 // Unlink the pCode label from it's pCode chain
5460 pic16_unlinkpCode(pc);
5462 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5463 // And link it into the instruction's pBranch labels. (Note, since
5464 // it's possible to have multiple labels associated with one instruction
5465 // we must provide a means to accomodate the additional labels. Thus
5466 // the labels are placed into the singly-linked list "label" as
5467 // opposed to being a single member of the pCodeInstruction.)
5469 //_ALLOC(pbr,sizeof(pBranch));
5470 pbr = Safe_calloc(1,sizeof(pBranch));
5474 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5477 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5479 } else if(pc->type == PC_CSOURCE) {
5481 /* merge the source line symbolic info into the next instruction */
5482 if((pcnext = pic16_findNextInstruction(pc) )) {
5484 // Unlink the pCode label from it's pCode chain
5485 pic16_unlinkpCode(pc);
5486 PCI(pcnext)->cline = PCCS(pc);
5487 //fprintf(stderr, "merging CSRC\n");
5488 //genericPrint(stderr,pcnext);
5494 pBlockRemoveUnusedLabels(pb);
5498 /*-----------------------------------------------------------------*/
5499 /*-----------------------------------------------------------------*/
5500 static int OptimizepCode(char dbName)
5502 #define MAX_PASSES 4
5511 DFPRINTF((stderr," Optimizing pCode\n"));
5515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5516 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5517 matches += OptimizepBlock(pb);
5520 while(matches && ++passes < MAX_PASSES);
5525 /*-----------------------------------------------------------------*/
5526 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5527 /*-----------------------------------------------------------------*/
5529 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5533 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5535 if( !( (pcop->type == PO_LABEL) ||
5536 (pcop->type == PO_LITERAL) ||
5537 (pcop->type == PO_STR) ))
5538 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5546 /*-----------------------------------------------------------------*/
5547 /*-----------------------------------------------------------------*/
5548 int InstructionRegBank(pCode *pc)
5552 if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5555 return REG_BANK(reg);
5560 /*-----------------------------------------------------------------*/
5561 /*-----------------------------------------------------------------*/
5562 static void FixRegisterBanking(pBlock *pb)
5573 //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5574 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5577 /* loop through all of the flow blocks with in one pblock */
5579 //fprintf(stderr,"Register banking\n");
5582 /* at this point, pc should point to a PC_FLOW object */
5585 /* for each flow block, determine the register banking
5590 //genericPrint(stderr, pc);
5592 reg = pic16_getRegFromInstruction(pc);
5595 fprintf(stderr, " %s ",reg->name);
5596 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
5597 reg->address,REG_BANK(reg),reg->isBitField);
5602 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
5603 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5607 /* Examine the instruction before this one to make sure it is
5608 * not a skip type instruction */
5609 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5611 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5614 reg_bank = (reg) ? REG_BANK(reg) : 0;
5616 if (cur_bank != reg_bank) {
5617 cur_bank = reg_bank;
5618 insertBankSwitch(0, pc, cur_bank);
5622 //fprintf(stderr, "Bummer can't switch banks\n");
5632 // } while(pc && !(isPCFL(pc)));
5637 if(pcprev && cur_bank) {
5639 int pos = 1; /* Assume that the bank switch instruction(s)
5640 * are inserted after this instruction */
5642 if((PCI(pcprev)->op == POC_RETLW) ||
5643 (PCI(pcprev)->op == POC_RETURN) ||
5644 (PCI(pcprev)->op == POC_RETFIE)) {
5646 /* oops, a RETURN - we need to switch banks *before* the RETURN */
5652 /* Brute force - make sure that we point to bank 0 at the
5653 * end of each flow block */
5655 insertBankSwitch(pos, pcprev, 0);
5657 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5658 pic16_pCodeInsertAfter(pcprev, new_pc);
5661 //fprintf(stderr, "Brute force switch\n");
5670 if(reg && REG_BANK(reg)!=cur_bank) {
5671 //fprintf(stderr,"need to switch banks\n");
5672 /* Examine the instruction before this one to make sure it is
5673 * not a skip type instruction */
5674 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5675 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5676 int b = cur_bank ^ REG_BANK(reg);
5678 cur_bank = REG_BANK(reg);
5684 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5687 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5688 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5692 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5693 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5695 insertBankSwitch(0, pc, -1, -1);
5704 static void pBlockDestruct(pBlock *pb)
5715 /*-----------------------------------------------------------------*/
5716 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5717 /* name dbName and combine them */
5718 /* into one block */
5719 /*-----------------------------------------------------------------*/
5720 static void mergepBlocks(char dbName)
5723 pBlock *pb, *pbmerged = NULL,*pbn;
5725 pb = the_pFile->pbHead;
5727 //fprintf(stderr," merging blocks named %c\n",dbName);
5731 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5732 if( getpBlock_dbName(pb) == dbName) {
5734 //fprintf(stderr," merged block %c\n",dbName);
5739 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
5740 /* pic16_addpCode2pBlock doesn't handle the tail: */
5741 pbmerged->pcTail = pb->pcTail;
5743 pb->prev->next = pbn;
5745 pbn->prev = pb->prev;
5750 //pic16_printpBlock(stderr, pbmerged);
5757 /*-----------------------------------------------------------------*/
5758 /* AnalyzeFlow - Examine the flow of the code and optimize */
5760 /* level 0 == minimal optimization */
5761 /* optimize registers that are used only by two instructions */
5762 /* level 1 == maximal optimization */
5763 /* optimize by looking at pairs of instructions that use the */
5765 /*-----------------------------------------------------------------*/
5767 static void AnalyzeFlow(int level)
5769 static int times_called=0;
5777 /* if this is not the first time this function has been called,
5778 then clean up old flow information */
5779 if(times_called++) {
5780 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5783 pic16_RegsUnMapLiveRanges();
5789 /* Phase 2 - Flow Analysis - Register Banking
5791 * In this phase, the individual flow blocks are examined
5792 * and register banking is fixed.
5795 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5796 //FixRegisterBanking(pb);
5798 /* Phase 2 - Flow Analysis
5800 * In this phase, the pCode is partition into pCodeFlow
5801 * blocks. The flow blocks mark the points where a continuous
5802 * stream of instructions changes flow (e.g. because of
5803 * a call or goto or whatever).
5806 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5807 pic16_BuildFlow(pb);
5810 /* Phase 2 - Flow Analysis - linking flow blocks
5812 * In this phase, the individual flow blocks are examined
5813 * to determine their order of excution.
5816 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5819 /* Phase 3 - Flow Analysis - Flow Tree
5821 * In this phase, the individual flow blocks are examined
5822 * to determine their order of excution.
5825 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5826 pic16_BuildFlowTree(pb);
5829 /* Phase x - Flow Analysis - Used Banks
5831 * In this phase, the individual flow blocks are examined
5832 * to determine the Register Banks they use
5835 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5839 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5840 pic16_pCodeRegMapLiveRanges(pb);
5842 pic16_RemoveUnusedRegisters();
5844 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5845 pic16_pCodeRegOptimizeRegUsage(level);
5851 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5855 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5857 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5858 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5859 pcflow = pcflow->next) {
5861 FillFlow(PCFL(pcflow));
5866 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5868 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5869 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5870 pcflow = pcflow->next) {
5872 FlowStats(PCFL(pcflow));
5878 /*-----------------------------------------------------------------*/
5879 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
5880 /* assigned to the registers. */
5882 /*-----------------------------------------------------------------*/
5884 void pic16_AnalyzeBanking(void)
5888 if(!pic16_picIsInitialized()) {
5889 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5890 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5891 fprintf(stderr,"support/scripts/inc2h.pl\n");
5892 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5897 /* Phase x - Flow Analysis - Used Banks
5899 * In this phase, the individual flow blocks are examined
5900 * to determine the Register Banks they use
5906 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5908 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5909 FixRegisterBanking(pb);
5913 /*-----------------------------------------------------------------*/
5914 /* buildCallTree - Look at the flow and extract all of the calls. */
5915 /*-----------------------------------------------------------------*/
5916 static set *register_usage(pBlock *pb);
5918 static void buildCallTree(void )
5929 /* Now build the call tree.
5930 First we examine all of the pCodes for functions.
5931 Keep in mind that the function boundaries coincide
5932 with pBlock boundaries.
5934 The algorithm goes something like this:
5935 We have two nested loops. The outer loop iterates
5936 through all of the pBlocks/functions. The inner
5937 loop iterates through all of the pCodes for
5938 a given pBlock. When we begin iterating through
5939 a pBlock, the variable pc_fstart, pCode of the start
5940 of a function, is cleared. We then search for pCodes
5941 of type PC_FUNCTION. When one is encountered, we
5942 initialize pc_fstart to this and at the same time
5943 associate a new pBranch object that signifies a
5944 branch entry. If a return is found, then this signifies
5945 a function exit point. We'll link the pCodes of these
5946 returns to the matching pc_fstart.
5948 When we're done, a doubly linked list of pBranches
5949 will exist. The head of this list is stored in
5950 `the_pFile', which is the meta structure for all
5951 of the pCode. Look at the pic16_printCallTree function
5952 on how the pBranches are linked together.
5955 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5956 pCode *pc_fstart=NULL;
5957 for(pc = pb->pcHead; pc; pc = pc->next) {
5959 if (PCF(pc)->fname) {
5961 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5962 //fprintf(stderr," found main \n");
5963 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5967 pbr = Safe_calloc(1,sizeof(pBranch));
5968 pbr->pc = pc_fstart = pc;
5971 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
5973 // Here's a better way of doing the same:
5974 addSet(&pb->function_entries, pc);
5977 // Found an exit point in a function, e.g. return
5978 // (Note, there may be more than one return per function)
5980 pBranchLink(PCF(pc_fstart), PCF(pc));
5982 addSet(&pb->function_exits, pc);
5984 } else if(isCALL(pc)) {
5985 addSet(&pb->function_calls,pc);
5990 /* Re-allocate the registers so that there are no collisions
5991 * between local variables when one function call another */
5994 // pic16_deallocateAllRegs();
5996 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6003 /*-----------------------------------------------------------------*/
6004 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6005 /* all of the logical connections. */
6007 /* Essentially what's done here is that the pCode flow is */
6009 /*-----------------------------------------------------------------*/
6011 void pic16_AnalyzepCode(char dbName)
6022 /* Phase 1 - Register allocation and peep hole optimization
6024 * The first part of the analysis is to determine the registers
6025 * that are used in the pCode. Once that is done, the peep rules
6026 * are applied to the code. We continue to loop until no more
6027 * peep rule optimizations are found (or until we exceed the
6028 * MAX_PASSES threshold).
6030 * When done, the required registers will be determined.
6036 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6037 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6039 /* First, merge the labels with the instructions */
6040 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6041 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6043 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6044 //fprintf(stderr," analyze and merging block %c\n",dbName);
6045 pic16_pBlockMergeLabels(pb);
6048 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6052 changes = OptimizepCode(dbName);
6054 } while(changes && (i++ < MAX_PASSES));
6059 /*-----------------------------------------------------------------*/
6060 /* ispCodeFunction - returns true if *pc is the pCode of a */
6062 /*-----------------------------------------------------------------*/
6063 static bool ispCodeFunction(pCode *pc)
6066 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6072 /*-----------------------------------------------------------------*/
6073 /* findFunction - Search for a function by name (given the name) */
6074 /* in the set of all functions that are in a pBlock */
6075 /* (note - I expect this to change because I'm planning to limit */
6076 /* pBlock's to just one function declaration */
6077 /*-----------------------------------------------------------------*/
6078 static pCode *findFunction(char *fname)
6085 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6087 pc = setFirstItem(pb->function_entries);
6090 if((pc->type == PC_FUNCTION) &&
6092 (strcmp(fname, PCF(pc)->fname)==0))
6095 pc = setNextItem(pb->function_entries);
6103 static void MarkUsedRegisters(set *regset)
6108 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6109 r2 = pic16_regWithIdx(r1->rIdx);
6115 static void pBlockStats(FILE *of, pBlock *pb)
6121 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6123 // for now just print the first element of each set
6124 pc = setFirstItem(pb->function_entries);
6126 fprintf(of,";entry: ");
6129 pc = setFirstItem(pb->function_exits);
6131 fprintf(of,";has an exit\n");
6135 pc = setFirstItem(pb->function_calls);
6137 fprintf(of,";functions called:\n");
6140 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6141 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6143 pc = setNextItem(pb->function_calls);
6147 r = setFirstItem(pb->tregisters);
6149 int n = elementsInSet(pb->tregisters);
6151 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6154 fprintf(of,"; %s\n",r->name);
6155 r = setNextItem(pb->tregisters);
6160 /*-----------------------------------------------------------------*/
6161 /*-----------------------------------------------------------------*/
6163 static void sequencepCode(void)
6169 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6171 pb->seq = GpCodeSequenceNumber+1;
6173 for( pc = pb->pcHead; pc; pc = pc->next)
6174 pc->seq = ++GpCodeSequenceNumber;
6180 /*-----------------------------------------------------------------*/
6181 /*-----------------------------------------------------------------*/
6182 static set *register_usage(pBlock *pb)
6185 set *registers=NULL;
6186 set *registersInCallPath = NULL;
6188 /* check recursion */
6190 pc = setFirstItem(pb->function_entries);
6197 if(pc->type != PC_FUNCTION)
6198 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6200 pc = setFirstItem(pb->function_calls);
6201 for( ; pc; pc = setNextItem(pb->function_calls)) {
6203 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6204 char *dest = pic16_get_op_from_instruction(PCI(pc));
6206 pcn = findFunction(dest);
6208 registersInCallPath = register_usage(pcn->pb);
6210 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6215 pBlockStats(stderr,pb); // debug
6218 // Mark the registers in this block as used.
6220 MarkUsedRegisters(pb->tregisters);
6221 if(registersInCallPath) {
6222 /* registers were used in the functions this pBlock has called */
6223 /* so now, we need to see if these collide with the ones we are */
6226 regs *r1,*r2, *newreg;
6228 DFPRINTF((stderr,"comparing registers\n"));
6230 r1 = setFirstItem(registersInCallPath);
6233 r2 = setFirstItem(pb->tregisters);
6235 while(r2 && (r1->type != REG_STK)) {
6237 if(r2->rIdx == r1->rIdx) {
6238 newreg = pic16_findFreeReg(REG_GPR);
6242 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6246 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6247 r1->rIdx, newreg->rIdx));
6248 r2->rIdx = newreg->rIdx;
6249 //if(r2->name) free(r2->name);
6251 r2->name = Safe_strdup(newreg->name);
6255 newreg->wasUsed = 1;
6257 r2 = setNextItem(pb->tregisters);
6260 r1 = setNextItem(registersInCallPath);
6263 /* Collisions have been resolved. Now free the registers in the call path */
6264 r1 = setFirstItem(registersInCallPath);
6266 if(r1->type != REG_STK) {
6267 newreg = pic16_regWithIdx(r1->rIdx);
6270 r1 = setNextItem(registersInCallPath);
6274 // MarkUsedRegisters(pb->registers);
6276 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6279 DFPRINTF((stderr,"returning regs\n"));
6281 DFPRINTF((stderr,"not returning regs\n"));
6283 DFPRINTF((stderr,"pBlock after register optim.\n"));
6284 pBlockStats(stderr,pb); // debug
6290 /*-----------------------------------------------------------------*/
6291 /* pct2 - writes the call tree to a file */
6293 /*-----------------------------------------------------------------*/
6294 static void pct2(FILE *of,pBlock *pb,int indent)
6298 // set *registersInCallPath = NULL;
6304 return; //recursion ?
6306 pc = setFirstItem(pb->function_entries);
6313 for(i=0;i<indent;i++) // Indentation
6316 if(pc->type == PC_FUNCTION)
6317 fprintf(of,"%s\n",PCF(pc)->fname);
6322 pc = setFirstItem(pb->function_calls);
6323 for( ; pc; pc = setNextItem(pb->function_calls)) {
6325 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6326 char *dest = pic16_get_op_from_instruction(PCI(pc));
6328 pcn = findFunction(dest);
6330 pct2(of,pcn->pb,indent+1);
6332 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6340 /*-----------------------------------------------------------------*/
6341 /* pic16_printCallTree - writes the call tree to a file */
6343 /*-----------------------------------------------------------------*/
6345 void pic16_printCallTree(FILE *of)
6357 fprintf(of, "\npBlock statistics\n");
6358 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6363 fprintf(of,"Call Tree\n");
6364 pbr = the_pFile->functions;
6368 if(!ispCodeFunction(pc))
6369 fprintf(of,"bug in call tree");
6372 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6374 while(pc->next && !ispCodeFunction(pc->next)) {
6376 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6377 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6385 fprintf(of,"\n**************\n\na better call tree\n");
6386 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6391 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6392 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6398 /*-----------------------------------------------------------------*/
6400 /*-----------------------------------------------------------------*/
6402 static void InlineFunction(pBlock *pb)
6410 pc = setFirstItem(pb->function_calls);
6412 for( ; pc; pc = setNextItem(pb->function_calls)) {
6415 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6421 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6423 //fprintf(stderr,"Cool can inline:\n");
6424 //pcn->print(stderr,pcn);
6426 //fprintf(stderr,"recursive call Inline\n");
6427 InlineFunction(pcn->pb);
6428 //fprintf(stderr,"return from recursive call Inline\n");
6431 At this point, *pc points to a CALL mnemonic, and
6432 *pcn points to the function that is being called.
6434 To in-line this call, we need to remove the CALL
6435 and RETURN(s), and link the function pCode in with
6441 /* Remove the CALL */
6445 /* remove callee pBlock from the pBlock linked list */
6446 removepBlock(pcn->pb);
6454 /* Remove the Function pCode */
6455 pct = pic16_findNextInstruction(pcn->next);
6457 /* Link the function with the callee */
6458 pc->next = pcn->next;
6459 pcn->next->prev = pc;
6461 /* Convert the function name into a label */
6463 pbr = Safe_calloc(1,sizeof(pBranch));
6464 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6466 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6467 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6469 /* turn all of the return's except the last into goto's */
6470 /* check case for 2 instruction pBlocks */
6471 pce = pic16_findNextInstruction(pcn->next);
6473 pCode *pce_next = pic16_findNextInstruction(pce->next);
6475 if(pce_next == NULL) {
6476 /* found the last return */
6477 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6479 //fprintf(stderr,"found last return\n");
6480 //pce->print(stderr,pce);
6481 pce->prev->next = pc_call->next;
6482 pc_call->next->prev = pce->prev;
6483 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6493 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6499 /*-----------------------------------------------------------------*/
6501 /*-----------------------------------------------------------------*/
6503 void pic16_InlinepCode(void)
6512 if(!functionInlining)
6515 /* Loop through all of the function definitions and count the
6516 * number of times each one is called */
6517 //fprintf(stderr,"inlining %d\n",__LINE__);
6519 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6521 pc = setFirstItem(pb->function_calls);
6523 for( ; pc; pc = setNextItem(pb->function_calls)) {
6526 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6527 if(pcn && isPCF(pcn)) {
6528 PCF(pcn)->ncalled++;
6531 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6536 //fprintf(stderr,"inlining %d\n",__LINE__);
6538 /* Now, Loop through the function definitions again, but this
6539 * time inline those functions that have only been called once. */
6541 InlineFunction(the_pFile->pbHead);
6542 //fprintf(stderr,"inlining %d\n",__LINE__);
6544 for(pb = the_pFile->pbHead; pb; pb = pb->next)