1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
63 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
65 static int mnemonics_initialized = 0;
68 static hTab *pic14MnemonicsHash = NULL;
69 static hTab *pic14pCodePeepCommandsHash = NULL;
73 static pFile *the_pFile = NULL;
74 static pBlock *pb_dead_pcodes = NULL;
76 /* Hardcoded flags to change the behavior of the PIC port */
77 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
78 static int functionInlining = 1; /* inline functions if nonzero */
79 int debug_verbose = 0; /* Set true to inundate .asm file */
81 // static int GpCodeSequenceNumber = 1;
84 extern void RemoveUnusedRegisters(void);
85 extern void RegsUnMapLiveRanges(void);
86 extern void BuildFlowTree(pBlock *pb);
87 extern void pCodeRegOptimizeRegUsage(int level);
88 extern int picIsInitialized(void);
90 /****************************************************************/
91 /* Forward declarations */
92 /****************************************************************/
94 void unlinkpCode(pCode *pc);
96 static void genericAnalyze(pCode *pc);
97 static void AnalyzeGOTO(pCode *pc);
98 static void AnalyzeSKIP(pCode *pc);
99 static void AnalyzeRETURN(pCode *pc);
102 static void genericDestruct(pCode *pc);
103 static void genericPrint(FILE *of,pCode *pc);
105 static void pCodePrintLabel(FILE *of, pCode *pc);
106 static void pCodePrintFunction(FILE *of, pCode *pc);
107 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
108 static char *get_op_from_instruction( pCodeInstruction *pcc);
109 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
110 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
111 int pCodePeepMatchRule(pCode *pc);
112 void pBlockStats(FILE *of, pBlock *pb);
113 pBlock *newpBlock(void);
114 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
115 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
116 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
117 void pCodeRegMapLiveRanges(pBlock *pb);
120 /****************************************************************/
121 /* PIC Instructions */
122 /****************************************************************/
124 pCodeInstruction pciADDWF = {
125 {PC_OPCODE, NULL, NULL, 0, NULL,
138 1,0, // dest, bit instruction
140 0, // literal operand
142 (PCC_W | PCC_REGISTER), // inCond
143 (PCC_REGISTER | PCC_Z) // outCond
146 pCodeInstruction pciADDFW = {
147 {PC_OPCODE, NULL, NULL, 0, NULL,
160 0,0, // dest, bit instruction
162 0, // literal operand
164 (PCC_W | PCC_REGISTER), // inCond
165 (PCC_W | PCC_Z) // outCond
168 pCodeInstruction pciADDLW = {
169 {PC_OPCODE, NULL, NULL, 0, NULL,
182 0,0, // dest, bit instruction
184 1, // literal operand
186 (PCC_W | PCC_LITERAL), // inCond
187 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
190 pCodeInstruction pciANDLW = {
191 {PC_OPCODE, NULL, NULL, 0, NULL,
204 0,0, // dest, bit instruction
206 1, // literal operand
208 (PCC_W | PCC_LITERAL), // inCond
209 (PCC_W | PCC_Z) // outCond
212 pCodeInstruction pciANDWF = {
213 {PC_OPCODE, NULL, NULL, 0, NULL,
226 1,0, // dest, bit instruction
228 0, // literal operand
230 (PCC_W | PCC_REGISTER), // inCond
231 (PCC_REGISTER | PCC_Z) // outCond
234 pCodeInstruction pciANDFW = {
235 {PC_OPCODE, NULL, NULL, 0, NULL,
248 0,0, // dest, bit instruction
250 0, // literal operand
252 (PCC_W | PCC_REGISTER), // inCond
253 (PCC_W | PCC_Z) // outCond
256 pCodeInstruction pciBCF = {
257 {PC_OPCODE, NULL, NULL, 0, NULL,
270 1,1, // dest, bit instruction
272 0, // literal operand
274 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
275 PCC_REGISTER // outCond
278 pCodeInstruction pciBSF = {
279 {PC_OPCODE, NULL, NULL, 0, NULL,
292 1,1, // dest, bit instruction
294 0, // literal operand
296 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
297 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
300 pCodeInstruction pciBTFSC = {
301 {PC_OPCODE, NULL, NULL, 0, NULL,
314 0,1, // dest, bit instruction
316 0, // literal operand
318 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
319 PCC_EXAMINE_PCOP // outCond
322 pCodeInstruction pciBTFSS = {
323 {PC_OPCODE, NULL, NULL, 0, NULL,
336 0,1, // dest, bit instruction
338 0, // literal operand
340 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
341 PCC_EXAMINE_PCOP // outCond
344 pCodeInstruction pciCALL = {
345 {PC_OPCODE, NULL, NULL, 0, NULL,
358 0,0, // dest, bit instruction
360 0, // literal operand
366 pCodeInstruction pciCOMF = {
367 {PC_OPCODE, NULL, NULL, 0, NULL,
380 1,0, // dest, bit instruction
382 0, // literal operand
384 PCC_REGISTER, // inCond
385 PCC_REGISTER // outCond
388 pCodeInstruction pciCOMFW = {
389 {PC_OPCODE, NULL, NULL, 0, NULL,
402 0,0, // dest, bit instruction
404 0, // literal operand
406 PCC_REGISTER, // inCond
410 pCodeInstruction pciCLRF = {
411 {PC_OPCODE, NULL, NULL, 0, NULL,
424 0,0, // dest, bit instruction
426 0, // literal operand
429 PCC_REGISTER // outCond
432 pCodeInstruction pciCLRW = {
433 {PC_OPCODE, NULL, NULL, 0, NULL,
446 0,0, // dest, bit instruction
448 0, // literal operand
454 pCodeInstruction pciCLRWDT = {
455 {PC_OPCODE, NULL, NULL, 0, NULL,
468 0,0, // dest, bit instruction
470 0, // literal operand
476 pCodeInstruction pciDECF = {
477 {PC_OPCODE, NULL, NULL, 0, NULL,
490 1,0, // dest, bit instruction
492 0, // literal operand
494 PCC_REGISTER, // inCond
495 PCC_REGISTER // outCond
498 pCodeInstruction pciDECFW = {
499 {PC_OPCODE, NULL, NULL, 0, NULL,
512 0,0, // dest, bit instruction
514 0, // literal operand
516 PCC_REGISTER, // inCond
520 pCodeInstruction pciDECFSZ = {
521 {PC_OPCODE, NULL, NULL, 0, NULL,
534 1,0, // dest, bit instruction
536 0, // literal operand
538 PCC_REGISTER, // inCond
539 PCC_REGISTER // outCond
542 pCodeInstruction pciDECFSZW = {
543 {PC_OPCODE, NULL, NULL, 0, NULL,
556 0,0, // dest, bit instruction
558 0, // literal operand
560 PCC_REGISTER, // inCond
564 pCodeInstruction pciGOTO = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 0,0, // dest, bit instruction
580 0, // literal operand
586 pCodeInstruction pciINCF = {
587 {PC_OPCODE, NULL, NULL, 0, NULL,
600 1,0, // dest, bit instruction
602 0, // literal operand
604 PCC_REGISTER, // inCond
605 PCC_REGISTER // outCond
608 pCodeInstruction pciINCFW = {
609 {PC_OPCODE, NULL, NULL, 0, NULL,
622 0,0, // dest, bit instruction
624 0, // literal operand
626 PCC_REGISTER, // inCond
630 pCodeInstruction pciINCFSZ = {
631 {PC_OPCODE, NULL, NULL, 0, NULL,
644 1,0, // dest, bit instruction
646 0, // literal operand
648 PCC_REGISTER, // inCond
649 PCC_REGISTER // outCond
652 pCodeInstruction pciINCFSZW = {
653 {PC_OPCODE, NULL, NULL, 0, NULL,
666 0,0, // dest, bit instruction
668 0, // literal operand
670 PCC_REGISTER, // inCond
674 pCodeInstruction pciIORWF = {
675 {PC_OPCODE, NULL, NULL, 0, NULL,
688 1,0, // dest, bit instruction
690 0, // literal operand
692 (PCC_W | PCC_REGISTER), // inCond
693 (PCC_REGISTER | PCC_Z) // outCond
696 pCodeInstruction pciIORFW = {
697 {PC_OPCODE, NULL, NULL, 0, NULL,
710 0,0, // dest, bit instruction
712 0, // literal operand
714 (PCC_W | PCC_REGISTER), // inCond
715 (PCC_W | PCC_Z) // outCond
718 pCodeInstruction pciIORLW = {
719 {PC_OPCODE, NULL, NULL, 0, NULL,
732 0,0, // dest, bit instruction
734 1, // literal operand
736 (PCC_W | PCC_LITERAL), // inCond
737 (PCC_W | PCC_Z) // outCond
740 pCodeInstruction pciMOVF = {
741 {PC_OPCODE, NULL, NULL, 0, NULL,
754 1,0, // dest, bit instruction
756 0, // literal operand
758 PCC_REGISTER, // inCond
762 pCodeInstruction pciMOVFW = {
763 {PC_OPCODE, NULL, NULL, 0, NULL,
776 0,0, // dest, bit instruction
778 0, // literal operand
780 PCC_REGISTER, // inCond
781 (PCC_W | PCC_Z) // outCond
784 pCodeInstruction pciMOVWF = {
785 {PC_OPCODE, NULL, NULL, 0, NULL,
798 0,0, // dest, bit instruction
800 0, // literal operand
803 PCC_REGISTER // outCond
806 pCodeInstruction pciMOVLW = {
807 {PC_OPCODE, NULL, NULL, 0, NULL,
819 0,0, // dest, bit instruction
821 1, // literal operand
823 (PCC_NONE | PCC_LITERAL), // inCond
827 pCodeInstruction pciNOP = {
828 {PC_OPCODE, NULL, NULL, 0, NULL,
840 0,0, // dest, bit instruction
842 0, // literal operand
848 pCodeInstruction pciRETFIE = {
849 {PC_OPCODE, NULL, NULL, 0, NULL,
862 0,0, // dest, bit instruction
864 0, // literal operand
867 PCC_NONE // outCond (not true... affects the GIE bit too)
870 pCodeInstruction pciRETLW = {
871 {PC_OPCODE, NULL, NULL, 0, NULL,
884 0,0, // dest, bit instruction
886 1, // literal operand
888 PCC_LITERAL, // inCond
892 pCodeInstruction pciRETURN = {
893 {PC_OPCODE, NULL, NULL, 0, NULL,
906 0,0, // dest, bit instruction
908 0, // literal operand
914 pCodeInstruction pciRLF = {
915 {PC_OPCODE, NULL, NULL, 0, NULL,
928 1,0, // dest, bit instruction
930 0, // literal operand
932 (PCC_C | PCC_REGISTER), // inCond
933 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
936 pCodeInstruction pciRLFW = {
937 {PC_OPCODE, NULL, NULL, 0, NULL,
950 0,0, // dest, bit instruction
952 0, // literal operand
954 (PCC_C | PCC_REGISTER), // inCond
955 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
958 pCodeInstruction pciRRF = {
959 {PC_OPCODE, NULL, NULL, 0, NULL,
972 1,0, // dest, bit instruction
974 0, // literal operand
976 (PCC_C | PCC_REGISTER), // inCond
977 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
980 pCodeInstruction pciRRFW = {
981 {PC_OPCODE, NULL, NULL, 0, NULL,
994 0,0, // dest, bit instruction
996 0, // literal operand
998 (PCC_C | PCC_REGISTER), // inCond
999 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1002 pCodeInstruction pciSUBWF = {
1003 {PC_OPCODE, NULL, NULL, 0, NULL,
1009 NULL, // from branch
1016 1,0, // dest, bit instruction
1017 0,0, // branch, skip
1018 0, // literal operand
1020 (PCC_W | PCC_REGISTER), // inCond
1021 (PCC_REGISTER | PCC_Z) // outCond
1024 pCodeInstruction pciSUBFW = {
1025 {PC_OPCODE, NULL, NULL, 0, NULL,
1031 NULL, // from branch
1038 0,0, // dest, bit instruction
1039 0,0, // branch, skip
1040 0, // literal operand
1042 (PCC_W | PCC_REGISTER), // inCond
1043 (PCC_W | PCC_Z) // outCond
1046 pCodeInstruction pciSUBLW = {
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 0,0, // branch, skip
1062 1, // literal operand
1064 (PCC_W | PCC_LITERAL), // inCond
1065 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1068 pCodeInstruction pciSWAPF = {
1069 {PC_OPCODE, NULL, NULL, 0, NULL,
1075 NULL, // from branch
1082 1,0, // dest, bit instruction
1083 0,0, // branch, skip
1084 0, // literal operand
1086 (PCC_REGISTER), // inCond
1087 (PCC_REGISTER) // outCond
1090 pCodeInstruction pciSWAPFW = {
1091 {PC_OPCODE, NULL, NULL, 0, NULL,
1097 NULL, // from branch
1104 0,0, // dest, bit instruction
1105 0,0, // branch, skip
1106 0, // literal operand
1108 (PCC_REGISTER), // inCond
1112 pCodeInstruction pciTRIS = {
1113 {PC_OPCODE, NULL, NULL, 0, NULL,
1119 NULL, // from branch
1126 0,0, // dest, bit instruction
1127 0,0, // branch, skip
1128 0, // literal operand
1131 PCC_REGISTER // outCond
1134 pCodeInstruction pciXORWF = {
1135 {PC_OPCODE, NULL, NULL, 0, NULL,
1141 NULL, // from branch
1148 1,0, // dest, bit instruction
1149 0,0, // branch, skip
1150 0, // literal operand
1152 (PCC_W | PCC_REGISTER), // inCond
1153 (PCC_REGISTER | PCC_Z) // outCond
1156 pCodeInstruction pciXORFW = {
1157 {PC_OPCODE, NULL, NULL, 0, NULL,
1163 NULL, // from branch
1170 0,0, // dest, bit instruction
1171 0,0, // branch, skip
1172 0, // literal operand
1174 (PCC_W | PCC_REGISTER), // inCond
1175 (PCC_W | PCC_Z) // outCond
1178 pCodeInstruction pciXORLW = {
1179 {PC_OPCODE, NULL, NULL, 0, NULL,
1185 NULL, // from branch
1192 0,0, // dest, bit instruction
1193 0,0, // branch, skip
1194 1, // literal operand
1196 (PCC_W | PCC_LITERAL), // inCond
1197 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1201 #define MAX_PIC14MNEMONICS 100
1202 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1205 #ifdef HAVE_VSNPRINTF
1206 // Alas, vsnprintf is not ANSI standard, and does not exist
1207 // on Solaris (and probably other non-Gnu flavored Unixes).
1209 /*-----------------------------------------------------------------*/
1210 /* SAFE_snprintf - like snprintf except the string pointer is */
1211 /* after the string has been printed to. This is */
1212 /* useful for printing to string as though if it */
1213 /* were a stream. */
1214 /*-----------------------------------------------------------------*/
1215 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1223 va_start(val, format);
1225 vsnprintf(*str, *size, format, val);
1230 if((size_t)len > *size) {
1231 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1232 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1240 #else // HAVE_VSNPRINTF
1242 // This version is *not* safe, despite the name.
1244 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1248 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1253 va_start(val, format);
1255 vsprintf(buffer, format, val);
1258 len = strlen(buffer);
1260 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1261 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1264 strcpy(*str, buffer);
1270 #endif // HAVE_VSNPRINTF
1273 extern void initStack(int base_address, int size);
1274 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1275 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1276 extern void init_pic(char *);
1278 void pCodeInitRegisters(void)
1280 static int initialized=0;
1281 int shareBankAddress;
1287 initStack(0xfff, 8);
1288 init_pic(port->processor);
1290 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1291 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1292 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1293 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1294 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1295 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1297 pc_status.rIdx = IDX_STATUS;
1298 pc_fsr.rIdx = IDX_FSR;
1299 pc_indf.rIdx = IDX_INDF;
1300 pc_intcon.rIdx = IDX_INTCON;
1301 pc_pcl.rIdx = IDX_PCL;
1302 pc_pclath.rIdx = IDX_PCLATH;
1304 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0); /* Known Zero - actually just a general purpose reg. */
1305 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x80); /* Interupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1306 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for status register. */
1307 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for pclath register. */
1309 pc_kzero.rIdx = pc_kzero.r->rIdx;
1310 pc_wsave.rIdx = pc_wsave.r->rIdx;
1311 pc_ssave.rIdx = pc_ssave.r->rIdx;
1312 pc_psave.rIdx = pc_psave.r->rIdx;
1314 shareBankAddress = 0x7f; /* FIXME - this is different for some PICs ICs if the sharebank does not exist then this address needs to be reserved across all banks. */
1315 pc_wsave.r->isFixed = 1;
1316 pc_wsave.r->address = shareBankAddress;
1318 /* probably should put this in a separate initialization routine */
1319 pb_dead_pcodes = newpBlock();
1323 /*-----------------------------------------------------------------*/
1324 /* mnem2key - convert a pic mnemonic into a hash key */
1325 /* (BTW - this spreads the mnemonics quite well) */
1327 /*-----------------------------------------------------------------*/
1329 int mnem2key(char const *mnem)
1338 key += toupper(*mnem++) +1;
1342 return (key & 0x1f);
1346 void pic14initMnemonics(void)
1351 pCodeInstruction *pci;
1353 if(mnemonics_initialized)
1356 //FIXME - probably should NULL out the array before making the assignments
1357 //since we check the array contents below this initialization.
1359 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1360 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1361 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1362 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1363 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1364 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1365 pic14Mnemonics[POC_BCF] = &pciBCF;
1366 pic14Mnemonics[POC_BSF] = &pciBSF;
1367 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1368 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1369 pic14Mnemonics[POC_CALL] = &pciCALL;
1370 pic14Mnemonics[POC_COMF] = &pciCOMF;
1371 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1372 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1373 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1374 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1375 pic14Mnemonics[POC_DECF] = &pciDECF;
1376 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1377 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1378 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1379 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1380 pic14Mnemonics[POC_INCF] = &pciINCF;
1381 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1382 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1383 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1384 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1385 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1386 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1387 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1388 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1389 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1390 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1391 pic14Mnemonics[POC_NOP] = &pciNOP;
1392 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1393 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1394 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1395 pic14Mnemonics[POC_RLF] = &pciRLF;
1396 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1397 pic14Mnemonics[POC_RRF] = &pciRRF;
1398 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1399 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1400 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1401 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1402 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1403 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1404 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1405 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1406 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1407 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1409 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1410 if(pic14Mnemonics[i])
1411 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1412 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1415 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1416 pci = hTabNextItem(pic14MnemonicsHash, &key);
1419 mnemonics_initialized = 1;
1422 int getpCodePeepCommand(char *cmd);
1424 int getpCode(char *mnem,unsigned dest)
1427 pCodeInstruction *pci;
1428 int key = mnem2key(mnem);
1430 if(!mnemonics_initialized)
1431 pic14initMnemonics();
1433 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1437 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1438 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1442 pci = hTabNextItemWK (pic14MnemonicsHash);
1449 /*-----------------------------------------------------------------*
1450 * pic14initpCodePeepCommands
1452 *-----------------------------------------------------------------*/
1453 void pic14initpCodePeepCommands(void)
1461 hTabAddItem(&pic14pCodePeepCommandsHash,
1462 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1464 } while (peepCommands[i].cmd);
1466 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1469 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1470 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1475 /*-----------------------------------------------------------------
1478 *-----------------------------------------------------------------*/
1480 int getpCodePeepCommand(char *cmd)
1484 int key = mnem2key(cmd);
1487 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1490 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1491 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1495 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1502 char getpBlock_dbName(pBlock *pb)
1508 return pb->cmemmap->dbName;
1512 void pBlockConvert2ISR(pBlock *pb)
1523 /*-----------------------------------------------------------------*/
1524 /* movepBlock2Head - given the dbname of a pBlock, move all */
1525 /* instances to the front of the doubly linked */
1526 /* list of pBlocks */
1527 /*-----------------------------------------------------------------*/
1529 void movepBlock2Head(char dbName)
1533 pb = the_pFile->pbHead;
1537 if(getpBlock_dbName(pb) == dbName) {
1538 pBlock *pbn = pb->next;
1539 pb->next = the_pFile->pbHead;
1540 the_pFile->pbHead->prev = pb;
1541 the_pFile->pbHead = pb;
1544 pb->prev->next = pbn;
1546 // If the pBlock that we just moved was the last
1547 // one in the link of all of the pBlocks, then we
1548 // need to point the tail to the block just before
1549 // the one we moved.
1550 // Note: if pb->next is NULL, then pb must have
1551 // been the last pBlock in the chain.
1554 pbn->prev = pb->prev;
1556 the_pFile->pbTail = pb->prev;
1567 void copypCode(FILE *of, char dbName)
1571 if(!of || !the_pFile)
1574 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1575 if(getpBlock_dbName(pb) == dbName) {
1583 void pcode_test(void)
1586 DFPRINTF((stderr,"pcode is alive!\n"));
1596 /* create the file name */
1597 strcpy(buffer,dstFileName);
1598 strcat(buffer,".p");
1600 if( !(pFile = fopen(buffer, "w" ))) {
1601 werror(E_FILE_OPEN_ERR,buffer);
1605 fprintf(pFile,"pcode dump\n\n");
1607 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1608 fprintf(pFile,"\n\tNew pBlock\n\n");
1610 fprintf(pFile,"%s",pb->cmemmap->sname);
1612 fprintf(pFile,"internal pblock");
1614 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1615 printpBlock(pFile,pb);
1619 /*-----------------------------------------------------------------*/
1620 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1621 /* ister, RegCond will return the bit being referenced. */
1623 /* fixme - why not just OR in the pcop bit field */
1624 /*-----------------------------------------------------------------*/
1626 static int RegCond(pCodeOp *pcop)
1632 if (pcop->type == PO_GPR_BIT) {
1633 char *name = pcop->name;
1635 name = PCOR(pcop)->r->name;
1636 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1637 switch(PCORB(pcop)->bit) {
1651 /*-----------------------------------------------------------------*/
1652 /* newpCode - create and return a newly initialized pCode */
1654 /* fixme - rename this */
1656 /* The purpose of this routine is to create a new Instruction */
1657 /* pCode. This is called by gen.c while the assembly code is being */
1661 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1662 /* (note that the op is analogous to but not the */
1663 /* same thing as the opcode of the instruction.) */
1664 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1667 /* a pointer to the new malloc'd pCode is returned. */
1671 /*-----------------------------------------------------------------*/
1672 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1674 pCodeInstruction *pci ;
1676 if(!mnemonics_initialized)
1677 pic14initMnemonics();
1679 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1681 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1682 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1685 if(pci->inCond & PCC_EXAMINE_PCOP)
1686 pci->inCond |= RegCond(pcop);
1688 if(pci->outCond & PCC_EXAMINE_PCOP)
1689 pci->outCond |= RegCond(pcop);
1691 pci->pc.prev = pci->pc.next = NULL;
1692 return (pCode *)pci;
1695 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1701 /*-----------------------------------------------------------------*/
1702 /* newpCodeWild - create a "wild" as in wild card pCode */
1704 /* Wild pcodes are used during the peep hole optimizer to serve */
1705 /* as place holders for any instruction. When a snippet of code is */
1706 /* compared to a peep hole rule, the wild card opcode will match */
1707 /* any instruction. However, the optional operand and label are */
1708 /* additional qualifiers that must also be matched before the */
1709 /* line (of assembly code) is declared matched. Note that the */
1710 /* operand may be wild too. */
1712 /* Note, a wild instruction is specified just like a wild var: */
1713 /* %4 ; A wild instruction, */
1714 /* See the peeph.def file for additional examples */
1716 /*-----------------------------------------------------------------*/
1718 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1723 pcw = Safe_calloc(1,sizeof(pCodeWild));
1725 pcw->pci.pc.type = PC_WILD;
1726 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1727 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1728 pcw->pci.pc.pb = NULL;
1730 // pcw->pci.pc.analyze = genericAnalyze;
1731 pcw->pci.pc.destruct = genericDestruct;
1732 pcw->pci.pc.print = genericPrint;
1734 pcw->id = pCodeID; // this is the 'n' in %n
1735 pcw->operand = optional_operand;
1736 pcw->label = optional_label;
1738 pcw->mustBeBitSkipInst = 0;
1739 pcw->mustNotBeBitSkipInst = 0;
1740 pcw->invertBitSkipInst = 0;
1742 return ( (pCode *)pcw);
1746 /*-----------------------------------------------------------------*/
1747 /* newPcodeInlineP - create a new pCode from a char string */
1748 /*-----------------------------------------------------------------*/
1751 pCode *newpCodeInlineP(char *cP)
1756 pcc = Safe_calloc(1,sizeof(pCodeComment));
1758 pcc->pc.type = PC_INLINE;
1759 pcc->pc.prev = pcc->pc.next = NULL;
1760 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1763 // pcc->pc.analyze = genericAnalyze;
1764 pcc->pc.destruct = genericDestruct;
1765 pcc->pc.print = genericPrint;
1768 pcc->comment = Safe_strdup(cP);
1770 pcc->comment = NULL;
1772 return ( (pCode *)pcc);
1776 /*-----------------------------------------------------------------*/
1777 /* newPcodeCharP - create a new pCode from a char string */
1778 /*-----------------------------------------------------------------*/
1780 pCode *newpCodeCharP(char *cP)
1785 pcc = Safe_calloc(1,sizeof(pCodeComment));
1787 pcc->pc.type = PC_COMMENT;
1788 pcc->pc.prev = pcc->pc.next = NULL;
1789 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1792 // pcc->pc.analyze = genericAnalyze;
1793 pcc->pc.destruct = genericDestruct;
1794 pcc->pc.print = genericPrint;
1797 pcc->comment = Safe_strdup(cP);
1799 pcc->comment = NULL;
1801 return ( (pCode *)pcc);
1805 /*-----------------------------------------------------------------*/
1806 /* newpCodeFunction - */
1807 /*-----------------------------------------------------------------*/
1810 pCode *newpCodeFunction(char *mod,char *f)
1814 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1815 //_ALLOC(pcf,sizeof(pCodeFunction));
1817 pcf->pc.type = PC_FUNCTION;
1818 pcf->pc.prev = pcf->pc.next = NULL;
1819 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1822 // pcf->pc.analyze = genericAnalyze;
1823 pcf->pc.destruct = genericDestruct;
1824 pcf->pc.print = pCodePrintFunction;
1829 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1830 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1831 strcpy(pcf->modname,mod);
1833 pcf->modname = NULL;
1836 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1837 pcf->fname = Safe_calloc(1,strlen(f)+1);
1838 strcpy(pcf->fname,f);
1842 return ( (pCode *)pcf);
1846 /*-----------------------------------------------------------------*/
1848 /*-----------------------------------------------------------------*/
1849 void destructpCodeFlow(pCode *pc)
1851 if(!pc || !isPCFL(pc))
1860 deleteSet(&PCFL(pc)->registers);
1861 deleteSet(&PCFL(pc)->from);
1862 deleteSet(&PCFL(pc)->to);
1867 pCode *newpCodeFlow(void )
1871 //_ALLOC(pcflow,sizeof(pCodeFlow));
1872 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1874 pcflow->pc.type = PC_FLOW;
1875 pcflow->pc.prev = pcflow->pc.next = NULL;
1876 pcflow->pc.pb = NULL;
1878 // pcflow->pc.analyze = genericAnalyze;
1879 pcflow->pc.destruct = destructpCodeFlow;
1880 pcflow->pc.print = genericPrint;
1882 pcflow->pc.seq = GpcFlowSeq++;
1884 pcflow->from = pcflow->to = NULL;
1886 pcflow->inCond = PCC_NONE;
1887 pcflow->outCond = PCC_NONE;
1889 pcflow->firstBank = -1;
1890 pcflow->lastBank = -1;
1892 pcflow->FromConflicts = 0;
1893 pcflow->ToConflicts = 0;
1897 pcflow->registers = newSet();
1899 return ( (pCode *)pcflow);
1903 /*-----------------------------------------------------------------*/
1904 /*-----------------------------------------------------------------*/
1905 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1907 pCodeFlowLink *pcflowLink;
1909 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1911 pcflowLink->pcflow = pcflow;
1912 pcflowLink->bank_conflict = 0;
1917 /*-----------------------------------------------------------------*/
1918 /* newpCodeCSource - create a new pCode Source Symbol */
1919 /*-----------------------------------------------------------------*/
1921 pCode *newpCodeCSource(int ln, char *f, char *l)
1926 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1928 pccs->pc.type = PC_CSOURCE;
1929 pccs->pc.prev = pccs->pc.next = NULL;
1932 pccs->pc.destruct = genericDestruct;
1933 pccs->pc.print = genericPrint;
1935 pccs->line_number = ln;
1937 pccs->line = Safe_strdup(l);
1942 pccs->file_name = Safe_strdup(f);
1944 pccs->file_name = NULL;
1946 return ( (pCode *)pccs);
1949 /*-----------------------------------------------------------------*/
1950 /* pCodeLabelDestruct - free memory used by a label. */
1951 /*-----------------------------------------------------------------*/
1952 static void pCodeLabelDestruct(pCode *pc)
1958 if((pc->type == PC_LABEL) && PCL(pc)->label)
1959 free(PCL(pc)->label);
1965 pCode *newpCodeLabel(char *name, int key)
1971 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1973 pcl->pc.type = PC_LABEL;
1974 pcl->pc.prev = pcl->pc.next = NULL;
1975 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1978 // pcl->pc.analyze = genericAnalyze;
1979 pcl->pc.destruct = pCodeLabelDestruct;
1980 pcl->pc.print = pCodePrintLabel;
1986 sprintf(s,"_%05d_DS_",key);
1991 pcl->label = Safe_strdup(s);
1993 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1994 return ( (pCode *)pcl);
1999 /*-----------------------------------------------------------------*/
2000 /* newpBlock - create and return a pointer to a new pBlock */
2001 /*-----------------------------------------------------------------*/
2002 pBlock *newpBlock(void)
2007 PpB = Safe_calloc(1,sizeof(pBlock) );
2008 PpB->next = PpB->prev = NULL;
2010 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2011 PpB->tregisters = NULL;
2013 PpB->FlowTree = NULL;
2019 /*-----------------------------------------------------------------*/
2020 /* newpCodeChain - create a new chain of pCodes */
2021 /*-----------------------------------------------------------------*
2023 * This function will create a new pBlock and the pointer to the
2024 * pCode that is passed in will be the first pCode in the block.
2025 *-----------------------------------------------------------------*/
2028 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2031 pBlock *pB = newpBlock();
2033 pB->pcHead = pB->pcTail = pc;
2040 /*-----------------------------------------------------------------*/
2041 /* newpCodeOpLabel - Create a new label given the key */
2042 /* Note, a negative key means that the label is part of wild card */
2043 /* (and hence a wild card label) used in the pCodePeep */
2044 /* optimizations). */
2045 /*-----------------------------------------------------------------*/
2047 pCodeOp *newpCodeOpLabel(char *name, int key)
2050 static int label_key=-1;
2054 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2055 pcop->type = PO_LABEL;
2060 sprintf(s=buffer,"_%05d_DS_",key);
2062 s = name, key = label_key--;
2064 PCOLAB(pcop)->offset = 0;
2066 pcop->name = Safe_strdup(s);
2068 ((pCodeOpLabel *)pcop)->key = key;
2070 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2074 /*-----------------------------------------------------------------*/
2075 /*-----------------------------------------------------------------*/
2076 pCodeOp *newpCodeOpLit(int lit)
2082 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2083 pcop->type = PO_LITERAL;
2087 sprintf(s,"0x%02x",lit);
2089 pcop->name = Safe_strdup(s);
2092 ((pCodeOpLit *)pcop)->lit = lit;
2097 /*-----------------------------------------------------------------*/
2098 /*-----------------------------------------------------------------*/
2099 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2103 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2104 pcop->type = PO_IMMEDIATE;
2107 pcop->name = Safe_strdup(name);
2110 r = dirregWithName(name);
2114 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2115 PCOI(pcop)->rIdx = r->rIdx;
2117 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2118 PCOI(pcop)->rIdx = -1;
2120 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2125 PCOI(pcop)->index = index;
2126 PCOI(pcop)->offset = offset;
2127 PCOI(pcop)->_const = code_space;
2128 PCOI(pcop)->_function = is_func;
2133 /*-----------------------------------------------------------------*/
2134 /*-----------------------------------------------------------------*/
2135 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2141 if(!pcwb || !subtype) {
2142 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2146 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2147 pcop->type = PO_WILD;
2148 sprintf(s,"%%%d",id);
2149 pcop->name = Safe_strdup(s);
2151 PCOW(pcop)->id = id;
2152 PCOW(pcop)->pcwb = pcwb;
2153 PCOW(pcop)->subtype = subtype;
2154 PCOW(pcop)->matched = NULL;
2159 /*-----------------------------------------------------------------*/
2160 /*-----------------------------------------------------------------*/
2161 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2166 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2167 pcop->type = PO_GPR_BIT;
2169 PCORB(pcop)->bit = bit;
2170 PCORB(pcop)->inBitSpace = inBitSpace;
2172 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2173 if (s && !inBitSpace) {
2174 r = dirregWithName(s);
2176 unsigned char idx = ((s[3] - (((s[3]>='0')&&(s[3]<='9'))?'0':'A'-10))<<4)|(s[4] - (((s[4]>='0')&&(s[4]<='9'))?'0':'A'-10));
2177 r = pic14_regWithIdx(idx);
2183 PCOR(pcop)->rIdx = r->rIdx;
2185 pcop->name = Safe_strdup(s);
2186 PCOR(pcop)->r = NULL;
2187 PCOR(pcop)->rIdx = 0;
2192 /*-----------------------------------------------------------------*
2193 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2195 * If rIdx >=0 then a specific register from the set of registers
2196 * will be selected. If rIdx <0, then a new register will be searched
2198 *-----------------------------------------------------------------*/
2200 pCodeOp *newpCodeOpReg(int rIdx)
2204 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2209 PCOR(pcop)->rIdx = rIdx;
2210 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2212 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2215 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2218 pcop->type = PCOR(pcop)->r->pc_type;
2223 pCodeOp *newpCodeOpRegFromStr(char *name)
2227 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2228 PCOR(pcop)->r = allocRegByName(name, 1);
2229 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2230 pcop->type = PCOR(pcop)->r->pc_type;
2231 pcop->name = PCOR(pcop)->r->name;
2236 /*-----------------------------------------------------------------*/
2237 /*-----------------------------------------------------------------*/
2239 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2246 pcop = newpCodeOpBit(name, -1,0);
2250 pcop = newpCodeOpLit(-1);
2254 pcop = newpCodeOpLabel(NULL,-1);
2257 pcop = newpCodeOpReg(-1);
2260 case PO_GPR_POINTER:
2261 case PO_GPR_REGISTER:
2263 pcop = newpCodeOpRegFromStr(name);
2265 pcop = newpCodeOpReg(-1);
2269 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2272 pcop->name = Safe_strdup(name);
2280 /*-----------------------------------------------------------------*/
2281 /*-----------------------------------------------------------------*/
2282 void pCodeConstString(char *name, char *value)
2286 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2291 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2295 sprintf(buffer,"; %s = %s",name,value);
2297 addpCode2pBlock(pb,newpCodeCharP(buffer));
2298 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2301 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2307 /*-----------------------------------------------------------------*/
2308 /*-----------------------------------------------------------------*/
2309 void pCodeReadCodeTable(void)
2313 fprintf(stderr, " %s\n",__FUNCTION__);
2315 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2319 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2320 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2321 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2322 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2324 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2325 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2326 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2327 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2332 /*-----------------------------------------------------------------*/
2333 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2334 /*-----------------------------------------------------------------*/
2335 void addpCode2pBlock(pBlock *pb, pCode *pc)
2342 /* If this is the first pcode to be added to a block that
2343 * was initialized with a NULL pcode, then go ahead and
2344 * make this pcode the head and tail */
2345 pb->pcHead = pb->pcTail = pc;
2348 pb->pcTail->next = pc;
2350 pc->prev = pb->pcTail;
2357 /*-----------------------------------------------------------------*/
2358 /* addpBlock - place a pBlock into the pFile */
2359 /*-----------------------------------------------------------------*/
2360 void addpBlock(pBlock *pb)
2362 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2365 /* First time called, we'll pass through here. */
2366 //_ALLOC(the_pFile,sizeof(pFile));
2367 the_pFile = Safe_calloc(1,sizeof(pFile));
2368 the_pFile->pbHead = the_pFile->pbTail = pb;
2369 the_pFile->functions = NULL;
2373 the_pFile->pbTail->next = pb;
2374 pb->prev = the_pFile->pbTail;
2376 the_pFile->pbTail = pb;
2379 /*-----------------------------------------------------------------*/
2380 /* removepBlock - remove a pBlock from the pFile */
2381 /*-----------------------------------------------------------------*/
2382 void removepBlock(pBlock *pb)
2390 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2392 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2395 if(pbs == the_pFile->pbHead)
2396 the_pFile->pbHead = pbs->next;
2398 if (pbs == the_pFile->pbTail)
2399 the_pFile->pbTail = pbs->prev;
2402 pbs->next->prev = pbs->prev;
2405 pbs->prev->next = pbs->next;
2412 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2416 /*-----------------------------------------------------------------*/
2417 /* printpCode - write the contents of a pCode to a file */
2418 /*-----------------------------------------------------------------*/
2419 void printpCode(FILE *of, pCode *pc)
2430 fprintf(of,"warning - unable to print pCode\n");
2433 /*-----------------------------------------------------------------*/
2434 /* printpBlock - write the contents of a pBlock to a file */
2435 /*-----------------------------------------------------------------*/
2436 void printpBlock(FILE *of, pBlock *pb)
2446 for(pc = pb->pcHead; pc; pc = pc->next)
2451 /*-----------------------------------------------------------------*/
2453 /* pCode processing */
2457 /*-----------------------------------------------------------------*/
2459 void unlinkpCode(pCode *pc)
2465 fprintf(stderr,"Unlinking: ");
2466 printpCode(stderr, pc);
2469 pc->prev->next = pc->next;
2471 pc->next->prev = pc->prev;
2473 pc->prev = pc->next = NULL;
2477 /*-----------------------------------------------------------------*/
2478 /*-----------------------------------------------------------------*/
2480 static void genericDestruct(pCode *pc)
2486 /* For instructions, tell the register (if there's one used)
2487 * that it's no longer needed */
2488 regs *reg = getRegFromInstruction(pc);
2490 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2493 /* Instead of deleting the memory used by this pCode, mark
2494 * the object as bad so that if there's a pointer to this pCode
2495 * dangling around somewhere then (hopefully) when the type is
2496 * checked we'll catch it.
2501 addpCode2pBlock(pb_dead_pcodes, pc);
2508 /*-----------------------------------------------------------------*/
2509 /*-----------------------------------------------------------------*/
2510 void pBlockRegs(FILE *of, pBlock *pb)
2515 r = setFirstItem(pb->tregisters);
2517 r = setNextItem(pb->tregisters);
2522 /*-----------------------------------------------------------------*/
2523 /*-----------------------------------------------------------------*/
2524 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2529 int use_buffer = 1; // copy the string to the passed buffer pointer
2534 use_buffer = 0; // Don't bother copying the string to the buffer.
2538 switch(pcop->type) {
2542 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2545 //return PCOR(pcop)->r->name;
2549 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2552 SAFE_snprintf(&buffer,&size,"%s",r->name);
2562 if(PCOI(pcop)->_const) {
2564 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2565 switch(PCOI(pcop)->offset) {
2567 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2570 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2573 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2576 8 * PCOI(pcop)->offset );
2579 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2582 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2583 SAFE_snprintf(&s,&size,"(%s + %d)",
2585 PCOI(pcop)->index );
2587 switch(PCOI(pcop)->offset) {
2589 SAFE_snprintf(&s,&size,"%s",pcop->name);
2592 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2595 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2604 //size = sizeof(buffer);
2605 if( PCOR(pcop)->instance) {
2606 SAFE_snprintf(&s,&size,"(%s + %d)",
2608 PCOR(pcop)->instance );
2609 //fprintf(stderr,"PO_DIR %s\n",buffer);
2611 SAFE_snprintf(&s,&size,"%s",pcop->name);
2617 if(PCOLAB(pcop)->offset == 1)
2618 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2620 SAFE_snprintf(&s,&size,"%s",pcop->name);
2627 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2636 return "NO operand";
2640 /*-----------------------------------------------------------------*/
2641 /*-----------------------------------------------------------------*/
2642 static char *get_op_from_instruction( pCodeInstruction *pcc)
2646 return get_op(pcc->pcop,NULL,0);
2648 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2649 return ("ERROR Null: "__FUNCTION__);
2651 return ("ERROR Null: get_op_from_instruction");
2655 /*-----------------------------------------------------------------*/
2656 /*-----------------------------------------------------------------*/
2657 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2660 fprintf(of,"pcodeopprint- not implemented\n");
2663 /*-----------------------------------------------------------------*/
2664 /*-----------------------------------------------------------------*/
2665 char *pCode2str(char *str, size_t size, pCode *pc)
2673 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2675 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2677 if(PCI(pc)->isBitInst) {
2678 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2679 char *name = PCI(pc)->pcop->name;
2681 name = PCOR(PCI(pc)->pcop)->r->name;
2682 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2683 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
2685 SAFE_snprintf(&s,&size,"%s,%d", name,
2686 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
2687 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2688 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2690 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2691 //PCI(pc)->pcop->t.bit );
2694 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2695 if( PCI(pc)->num_ops == 2)
2696 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2698 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2701 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2703 if( PCI(pc)->num_ops == 2)
2704 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2712 /* assuming that comment ends with a \n */
2713 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2717 /* assuming that inline code ends with a \n */
2718 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2722 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2725 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2728 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2731 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2734 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2738 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2745 /*-----------------------------------------------------------------*/
2746 /* genericPrint - the contents of a pCode to a file */
2747 /*-----------------------------------------------------------------*/
2748 static void genericPrint(FILE *of, pCode *pc)
2756 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2760 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2764 // If the opcode has a label, print that first
2766 pBranch *pbl = PCI(pc)->label;
2767 while(pbl && pbl->pc) {
2768 if(pbl->pc->type == PC_LABEL)
2769 pCodePrintLabel(of, pbl->pc);
2775 genericPrint(of,PCODE(PCI(pc)->cline));
2780 pCode2str(str, 256, pc);
2782 fprintf(of,"%s",str);
2786 fprintf(of, "\t;key=%03x",pc->seq);
2788 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2793 pBranch *dpb = pc->to; // debug
2795 switch ( dpb->pc->type) {
2797 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2800 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2803 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2806 fprintf(of, "\t;flow");
2820 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2821 if(PCW(pc)->pci.label)
2822 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2824 if(PCW(pc)->operand) {
2825 fprintf(of,";\toperand ");
2826 pCodeOpPrint(of,PCW(pc)->operand );
2832 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2833 if(PCFL(pc)->ancestor)
2834 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2841 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2845 fprintf(of,"unknown pCode type %d\n",pc->type);
2850 /*-----------------------------------------------------------------*/
2851 /* pCodePrintFunction - prints function begin/end */
2852 /*-----------------------------------------------------------------*/
2854 static void pCodePrintFunction(FILE *of, pCode *pc)
2860 if( ((pCodeFunction *)pc)->modname)
2861 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2863 if(PCF(pc)->fname) {
2864 pBranch *exits = PCF(pc)->to;
2866 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2869 exits = exits->next;
2872 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2875 if((PCF(pc)->from &&
2876 PCF(pc)->from->pc->type == PC_FUNCTION &&
2877 PCF(PCF(pc)->from->pc)->fname) )
2878 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2880 fprintf(of,"; exit point [can't find entry point]\n");
2883 /*-----------------------------------------------------------------*/
2884 /* pCodePrintLabel - prints label */
2885 /*-----------------------------------------------------------------*/
2887 static void pCodePrintLabel(FILE *of, pCode *pc)
2894 fprintf(of,"%s\n",PCL(pc)->label);
2895 else if (PCL(pc)->key >=0)
2896 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2898 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2901 /*-----------------------------------------------------------------*/
2902 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2903 /* remove it if it is found. */
2904 /*-----------------------------------------------------------------*/
2905 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2912 if(pcl->type == PC_OPCODE)
2913 b = PCI(pcl)->label;
2915 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2920 //fprintf (stderr, "%s \n",__FUNCTION__);
2921 //pcl->print(stderr,pcl);
2922 //pc->print(stderr,pc);
2925 //fprintf (stderr, "found label\n");
2929 bprev->next = b->next; /* Not first pCode in chain */
2933 PCI(pcl)->label = b->next; /* First pCode in chain */
2936 return; /* A label can't occur more than once */
2944 /*-----------------------------------------------------------------*/
2945 /*-----------------------------------------------------------------*/
2946 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2965 /*-----------------------------------------------------------------*/
2966 /* pBranchLink - given two pcodes, this function will link them */
2967 /* together through their pBranches */
2968 /*-----------------------------------------------------------------*/
2969 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2973 // Declare a new branch object for the 'from' pCode.
2975 //_ALLOC(b,sizeof(pBranch));
2976 b = Safe_calloc(1,sizeof(pBranch));
2977 b->pc = PCODE(t); // The link to the 'to' pCode.
2980 f->to = pBranchAppend(f->to,b);
2982 // Now do the same for the 'to' pCode.
2984 //_ALLOC(b,sizeof(pBranch));
2985 b = Safe_calloc(1,sizeof(pBranch));
2989 t->from = pBranchAppend(t->from,b);
2994 /*-----------------------------------------------------------------*/
2995 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2997 /*-----------------------------------------------------------------*/
2998 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3011 /*-----------------------------------------------------------------*/
3012 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3013 /*-----------------------------------------------------------------*/
3014 static void pCodeUnlink(pCode *pc)
3019 if(!pc->prev || !pc->next) {
3020 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3024 /* first remove the pCode from the chain */
3025 pc->prev->next = pc->next;
3026 pc->next->prev = pc->prev;
3028 /* Now for the hard part... */
3030 /* Remove the branches */
3034 pc1 = pb1->pc; /* Get the pCode that branches to the
3035 * one we're unlinking */
3037 /* search for the link back to this pCode (the one we're
3039 if(pb2 = pBranchFind(pc1->to,pc)) {
3040 pb2->pc = pc->to->pc; // make the replacement
3042 /* if the pCode we're unlinking contains multiple 'to'
3043 * branches (e.g. this a skip instruction) then we need
3044 * to copy these extra branches to the chain. */
3046 pBranchAppend(pb2, pc->to->next);
3055 /*-----------------------------------------------------------------*/
3056 /*-----------------------------------------------------------------*/
3058 static void genericAnalyze(pCode *pc)
3068 // Go through the pCodes that are in pCode chain and link
3069 // them together through the pBranches. Note, the pCodes
3070 // are linked together as a contiguous stream like the
3071 // assembly source code lines. The linking here mimics this
3072 // except that comments are not linked in.
3074 pCode *npc = pc->next;
3076 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3077 pBranchLink(pc,npc);
3082 /* reached the end of the pcode chain without finding
3083 * an instruction we could link to. */
3087 fprintf(stderr,"analyze PC_FLOW\n");
3091 fprintf(stderr,,";A bad pCode is being used\n");
3097 /*-----------------------------------------------------------------*/
3098 /*-----------------------------------------------------------------*/
3099 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3103 if(pc->type == PC_LABEL) {
3104 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3107 if(pc->type == PC_OPCODE) {
3108 pbr = PCI(pc)->label;
3110 if(pbr->pc->type == PC_LABEL) {
3111 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3121 /*-----------------------------------------------------------------*/
3122 /*-----------------------------------------------------------------*/
3123 int checkLabel(pCode *pc)
3127 if(pc && isPCI(pc)) {
3128 pbr = PCI(pc)->label;
3130 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3140 /*-----------------------------------------------------------------*/
3141 /* findLabelinpBlock - Search the pCode for a particular label */
3142 /*-----------------------------------------------------------------*/
3143 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3150 for(pc = pb->pcHead; pc; pc = pc->next)
3151 if(compareLabel(pc,pcop_label))
3157 /*-----------------------------------------------------------------*/
3158 /* findLabel - Search the pCode for a particular label */
3159 /*-----------------------------------------------------------------*/
3160 pCode * findLabel(pCodeOpLabel *pcop_label)
3168 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3169 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3173 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3177 /*-----------------------------------------------------------------*/
3178 /* findNextpCode - given a pCode, find the next of type 'pct' */
3179 /* in the linked list */
3180 /*-----------------------------------------------------------------*/
3181 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3194 /*-----------------------------------------------------------------*/
3195 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3196 /* in the linked list */
3197 /*-----------------------------------------------------------------*/
3198 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3210 /*-----------------------------------------------------------------*/
3211 /* findNextInstruction - given a pCode, find the next instruction */
3212 /* in the linked list */
3213 /*-----------------------------------------------------------------*/
3214 pCode * findNextInstruction(pCode *pci)
3219 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3223 fprintf(stderr,"findNextInstruction: ");
3224 printpCode(stderr, pc);
3229 //fprintf(stderr,"Couldn't find instruction\n");
3233 /*-----------------------------------------------------------------*/
3234 /* findNextInstruction - given a pCode, find the next instruction */
3235 /* in the linked list */
3236 /*-----------------------------------------------------------------*/
3237 pCode * findPrevInstruction(pCode *pci)
3239 return findPrevpCode(pci, PC_OPCODE);
3242 /*-----------------------------------------------------------------*/
3243 /* findFunctionEnd - given a pCode find the end of the function */
3244 /* that contains it */
3245 /*-----------------------------------------------------------------*/
3246 pCode * findFunctionEnd(pCode *pc)
3250 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3256 fprintf(stderr,"Couldn't find function end\n");
3261 /*-----------------------------------------------------------------*/
3262 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3263 /* instruction with which it is associated. */
3264 /*-----------------------------------------------------------------*/
3265 static void AnalyzeLabel(pCode *pc)
3274 static void AnalyzeGOTO(pCode *pc)
3277 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3281 static void AnalyzeSKIP(pCode *pc)
3284 pBranchLink(pc,findNextInstruction(pc->next));
3285 pBranchLink(pc,findNextInstruction(pc->next->next));
3289 static void AnalyzeRETURN(pCode *pc)
3292 // branch_link(pc,findFunctionEnd(pc->next));
3298 /*-----------------------------------------------------------------*/
3299 /*-----------------------------------------------------------------*/
3300 regs * getRegFromInstruction(pCode *pc)
3306 PCI(pc)->num_ops == 0 )
3309 switch(PCI(pc)->pcop->type) {
3312 return PCOR(PCI(pc)->pcop)->r;
3314 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3318 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3319 return PCOR(PCI(pc)->pcop)->r;
3322 if(PCOI(PCI(pc)->pcop)->r)
3323 return (PCOI(PCI(pc)->pcop)->r);
3325 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3326 return dirregWithName(PCI(pc)->pcop->name);
3327 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3330 return PCOR(PCI(pc)->pcop)->r;
3333 //fprintf(stderr, "getRegFromInstruction - dir\n");
3334 return PCOR(PCI(pc)->pcop)->r;
3336 //fprintf(stderr, "getRegFromInstruction - literal\n");
3340 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3341 //genericPrint(stderr, pc);
3349 /*-----------------------------------------------------------------*/
3350 /*-----------------------------------------------------------------*/
3352 void AnalyzepBlock(pBlock *pb)
3359 /* Find all of the registers used in this pBlock
3360 * by looking at each instruction and examining it's
3363 for(pc = pb->pcHead; pc; pc = pc->next) {
3365 /* Is this an instruction with operands? */
3366 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3368 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3369 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3371 /* Loop through all of the registers declared so far in
3372 this block and see if we find this one there */
3374 regs *r = setFirstItem(pb->tregisters);
3377 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3378 PCOR(PCI(pc)->pcop)->r = r;
3381 r = setNextItem(pb->tregisters);
3385 /* register wasn't found */
3386 //r = Safe_calloc(1, sizeof(regs));
3387 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3388 //addSet(&pb->tregisters, r);
3389 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3390 //PCOR(PCI(pc)->pcop)->r = r;
3391 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3393 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3396 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3397 if(PCOR(PCI(pc)->pcop)->r) {
3398 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3399 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3401 if(PCI(pc)->pcop->name)
3402 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3404 fprintf(stderr,"ERROR: NULL register\n");
3413 /*-----------------------------------------------------------------*/
3415 /*-----------------------------------------------------------------*/
3416 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3418 void InsertpFlow(pCode *pc, pCode **pflow)
3421 PCFL(*pflow)->end = pc;
3423 if(!pc || !pc->next)
3426 *pflow = newpCodeFlow();
3427 pCodeInsertAfter(pc, *pflow);
3430 /*-----------------------------------------------------------------*/
3431 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3432 /* the flow blocks. */
3434 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3435 * point the instruction flow changes.
3437 /*-----------------------------------------------------------------*/
3438 void BuildFlow(pBlock *pb)
3441 pCode *last_pci=NULL;
3448 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3449 /* Insert a pCodeFlow object at the beginning of a pBlock */
3451 InsertpFlow(pb->pcHead, &pflow);
3453 //pflow = newpCodeFlow(); /* Create a new Flow object */
3454 //pflow->next = pb->pcHead; /* Make the current head the next object */
3455 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3456 //pb->pcHead = pflow; /* Make the Flow object the head */
3459 for( pc = findNextInstruction(pb->pcHead);
3461 pc=findNextInstruction(pc)) {
3464 PCI(pc)->pcflow = PCFL(pflow);
3466 //fprintf(stderr," build: ");
3467 //pflow->print(stderr,pflow);
3469 if( PCI(pc)->isSkip) {
3471 /* The two instructions immediately following this one
3472 * mark the beginning of a new flow segment */
3474 while(pc && PCI(pc)->isSkip) {
3476 PCI(pc)->pcflow = PCFL(pflow);
3480 InsertpFlow(pc, &pflow);
3481 pc=findNextInstruction(pc->next);
3489 PCI(pc)->pcflow = PCFL(pflow);
3491 InsertpFlow(pc, &pflow);
3493 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3495 InsertpFlow(pc, &pflow);
3498 } else if (checkLabel(pc)) {
3500 /* This instruction marks the beginning of a
3501 * new flow segment */
3506 /* If the previous pCode is not a flow object, then
3507 * insert a new flow object. (This check prevents
3508 * two consecutive flow objects from being insert in
3509 * the case where a skip instruction preceeds an
3510 * instruction containing a label.) */
3512 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3513 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3515 PCI(pc)->pcflow = PCFL(pflow);
3522 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3524 PCFL(pflow)->end = pb->pcTail;
3527 /*-------------------------------------------------------------------*/
3528 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3529 /* the flow blocks. */
3531 * unBuildFlow removes pCodeFlow objects from a pCode chain
3533 /*-----------------------------------------------------------------*/
3534 void unBuildFlow(pBlock *pb)
3549 if(PCI(pc)->pcflow) {
3550 //free(PCI(pc)->pcflow);
3551 PCI(pc)->pcflow = NULL;
3554 } else if(isPCFL(pc) )
3563 /*-----------------------------------------------------------------*/
3564 /*-----------------------------------------------------------------*/
3565 void dumpCond(int cond)
3568 static char *pcc_str[] = {
3582 int ncond = sizeof(pcc_str) / sizeof(char *);
3585 fprintf(stderr, "0x%04X\n",cond);
3587 for(i=0,j=1; i<ncond; i++, j<<=1)
3589 fprintf(stderr, " %s\n",pcc_str[i]);
3593 /*-----------------------------------------------------------------*/
3594 /*-----------------------------------------------------------------*/
3595 void FlowStats(pCodeFlow *pcflow)
3603 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3605 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3608 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3613 fprintf(stderr, " FlowStats inCond: ");
3614 dumpCond(pcflow->inCond);
3615 fprintf(stderr, " FlowStats outCond: ");
3616 dumpCond(pcflow->outCond);
3620 /*-----------------------------------------------------------------*
3621 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3622 * if it affects the banking bits.
3624 * return: -1 == Banking bits are unaffected by this pCode.
3626 * return: > 0 == Banking bits are affected.
3628 * If the banking bits are affected, then the returned value describes
3629 * which bits are affected and how they're affected. The lower half
3630 * of the integer maps to the bits that are affected, the upper half
3631 * to whether they're set or cleared.
3633 *-----------------------------------------------------------------*/
3634 #define SET_BANK_BIT (1 << 16)
3635 #define CLR_BANK_BIT 0
3637 int isBankInstruction(pCode *pc)
3645 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3647 /* Check to see if the register banks are changing */
3648 if(PCI(pc)->isModReg) {
3650 pCodeOp *pcop = PCI(pc)->pcop;
3651 switch(PCI(pc)->op) {
3654 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3655 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3656 return SET_BANK_BIT | PIC_RP0_BIT;
3659 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3660 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3661 return CLR_BANK_BIT | PIC_RP0_BIT;
3666 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3667 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3668 return CLR_BANK_BIT | PIC_RP1_BIT;
3670 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3671 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3672 return CLR_BANK_BIT | PIC_RP1_BIT;
3676 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3677 //genericPrint(stderr, pc);
3688 /*-----------------------------------------------------------------*/
3689 /*-----------------------------------------------------------------*/
3690 void FillFlow(pCodeFlow *pcflow)
3699 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3701 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3704 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3711 isBankInstruction(pc);
3713 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3717 fprintf(stderr, " FillFlow - Bad end of flow\n");
3719 fprintf(stderr, " FillFlow - Ending flow with\n ");
3720 pc->print(stderr,pc);
3723 fprintf(stderr, " FillFlow inCond: ");
3724 dumpCond(pcflow->inCond);
3725 fprintf(stderr, " FillFlow outCond: ");
3726 dumpCond(pcflow->outCond);
3730 /*-----------------------------------------------------------------*/
3731 /*-----------------------------------------------------------------*/
3732 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3734 pCodeFlowLink *fromLink, *toLink;
3736 if(!from || !to || !to->pcflow || !from->pcflow)
3739 fromLink = newpCodeFlowLink(from->pcflow);
3740 toLink = newpCodeFlowLink(to->pcflow);
3742 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3743 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3747 /*-----------------------------------------------------------------*
3748 * void LinkFlow(pBlock *pb)
3750 * In BuildFlow, the PIC code has been partitioned into contiguous
3751 * non-branching segments. In LinkFlow, we determine the execution
3752 * order of these segments. For example, if one of the segments ends
3753 * with a skip, then we know that there are two possible flow segments
3754 * to which control may be passed.
3755 *-----------------------------------------------------------------*/
3756 void LinkFlow(pBlock *pb)
3762 //fprintf(stderr,"linkflow \n");
3764 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3766 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3769 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3771 //fprintf(stderr," link: ");
3772 //pcflow->print(stderr,pcflow);
3774 //FillFlow(PCFL(pcflow));
3776 pc = PCFL(pcflow)->end;
3778 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3779 if(isPCI_SKIP(pc)) {
3780 //fprintf(stderr, "ends with skip\n");
3781 //pc->print(stderr,pc);
3782 pct=findNextInstruction(pc->next);
3783 LinkFlow_pCode(PCI(pc),PCI(pct));
3784 pct=findNextInstruction(pct->next);
3785 LinkFlow_pCode(PCI(pc),PCI(pct));
3789 if(isPCI_BRANCH(pc)) {
3790 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3792 //fprintf(stderr, "ends with branch\n ");
3793 //pc->print(stderr,pc);
3795 if(!(pcol && isPCOLAB(pcol))) {
3796 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3797 pc->print(stderr,pc);
3798 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3803 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3804 LinkFlow_pCode(PCI(pc),PCI(pct));
3806 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3807 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3808 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3814 //fprintf(stderr, "ends with non-branching instruction:\n");
3815 //pc->print(stderr,pc);
3817 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3823 //fprintf(stderr, "ends with unknown\n");
3824 //pc->print(stderr,pc);
3828 //fprintf(stderr, "ends with nothing: ERROR\n");
3832 /*-----------------------------------------------------------------*/
3833 /*-----------------------------------------------------------------*/
3835 /*-----------------------------------------------------------------*/
3836 /*-----------------------------------------------------------------*/
3837 int isPCinFlow(pCode *pc, pCode *pcflow)
3843 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3846 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3852 /*-----------------------------------------------------------------*/
3853 /*-----------------------------------------------------------------*/
3854 void BanksUsedFlow2(pCode *pcflow)
3863 if(!isPCFL(pcflow)) {
3864 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3868 pc = findNextInstruction(pcflow->next);
3870 PCFL(pcflow)->lastBank = -1;
3872 while(isPCinFlow(pc,pcflow)) {
3874 int bank_selected = isBankInstruction(pc);
3876 //if(PCI(pc)->pcflow)
3877 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3879 if(bank_selected > 0) {
3880 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3882 /* This instruction is modifying banking bits before accessing registers */
3884 PCFL(pcflow)->firstBank = -1;
3886 if(PCFL(pcflow)->lastBank == -1)
3887 PCFL(pcflow)->lastBank = 0;
3889 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3890 if(bank_selected & SET_BANK_BIT)
3891 PCFL(pcflow)->lastBank |= bank;
3895 reg = getRegFromInstruction(pc);
3897 if(reg && !isREGinBank(reg, bank)) {
3898 int allbanks = REGallBanks(reg);
3900 PCFL(pcflow)->firstBank = allbanks;
3902 PCFL(pcflow)->lastBank = allbanks;
3909 pc = findNextInstruction(pc->next);
3912 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3913 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3918 /*-----------------------------------------------------------------*/
3919 /*-----------------------------------------------------------------*/
3920 void BanksUsedFlow(pBlock *pb)
3925 //pb->pcHead->print(stderr, pb->pcHead);
3927 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3928 //pcflow->print(stderr,pcflow);
3930 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3932 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3934 BanksUsedFlow2(pcflow);
3940 /*-----------------------------------------------------------------*/
3941 /*-----------------------------------------------------------------*/
3942 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3950 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3952 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3953 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3956 /* insert the bank switch after this pc instruction */
3957 pCode *pcnext = findNextInstruction(pc);
3958 pCodeInsertAfter(pc, new_pc);
3963 pCodeInsertAfter(pc->prev, new_pc);
3965 /* Move the label, if there is one */
3967 if(PCI(pc)->label) {
3968 PCI(new_pc)->label = PCI(pc)->label;
3969 PCI(pc)->label = NULL;
3972 /* The new instruction has the same pcflow block */
3973 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3976 /*-----------------------------------------------------------------*/
3977 /*-----------------------------------------------------------------*/
3978 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3989 pc = findNextInstruction(pcfl->pc.next);
3991 while(isPCinFlow(pc,PCODE(pcfl))) {
3993 reg = getRegFromInstruction(pc);
3996 fprintf(stderr, " %s ",reg->name);
3997 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4002 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4003 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4006 /* Examine the instruction before this one to make sure it is
4007 * not a skip type instruction */
4008 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4010 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4014 reg_bank = (reg) ? REG_BANK(reg) : 0;
4016 b = cur_bank ^ reg_bank;
4018 //fprintf(stderr, "Cool! can switch banks\n");
4019 cur_bank = reg_bank;
4024 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4027 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4028 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4032 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4033 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4035 insertBankSwitch(0, pc, -1, -1);
4041 //fprintf(stderr, "Bummer can't switch banks\n");
4047 pc = findNextInstruction(pc->next);
4051 if(pcprev && cur_bank) {
4052 /* Brute force - make sure that we point to bank 0 at the
4053 * end of each flow block */
4054 new_pc = newpCode(POC_BCF,
4055 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4056 pCodeInsertAfter(pcprev, new_pc);
4062 /*-----------------------------------------------------------------*/
4063 /*int compareBankFlow - compare the banking requirements between */
4065 /*-----------------------------------------------------------------*/
4066 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4069 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4072 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4075 if(pcflow->firstBank == -1)
4079 if(pcflowLink->pcflow->firstBank == -1) {
4080 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4081 pcflowLink->pcflow->to :
4082 pcflowLink->pcflow->from);
4083 return compareBankFlow(pcflow, pctl, toORfrom);
4087 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4090 pcflowLink->bank_conflict++;
4091 pcflowLink->pcflow->FromConflicts++;
4092 pcflow->ToConflicts++;
4095 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4098 pcflowLink->bank_conflict++;
4099 pcflowLink->pcflow->ToConflicts++;
4100 pcflow->FromConflicts++;
4104 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4105 pcflowLink->pcflow->pc.seq,
4106 pcflowLink->pcflow->FromConflicts,
4107 pcflowLink->pcflow->ToConflicts);
4112 /*-----------------------------------------------------------------*/
4113 /*-----------------------------------------------------------------*/
4114 void FixBankFlow(pBlock *pb)
4118 pCodeFlowLink *pcfl;
4120 pCode *pcflow_max_To=NULL;
4121 pCode *pcflow_max_From=NULL;
4122 int max_ToConflicts=0;
4123 int max_FromConflicts=0;
4125 //fprintf(stderr,"Fix Bank flow \n");
4126 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4130 First loop through all of the flow objects in this pcode block
4131 and fix the ones that have banking conflicts between the
4135 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4137 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4139 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4141 if(!isPCFL(pcflow)) {
4142 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4146 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4147 PCFL(pcflow)->firstBank >= 0 &&
4148 PCFL(pcflow)->lastBank >= 0 ) {
4150 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4151 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4153 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4154 BanksUsedFlow2(pcflow);
4159 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4161 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4163 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4168 if(!isPCFL(pcflow)) {
4169 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4173 PCFL(pcflow)->FromConflicts = 0;
4174 PCFL(pcflow)->ToConflicts = 0;
4179 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4180 pcfl = setFirstItem(PCFL(pcflow)->from);
4183 pc = PCODE(pcfl->pcflow);
4186 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4187 pc->print(stderr,pc);
4190 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4193 pcfl=setNextItem(PCFL(pcflow)->from);
4196 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4197 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4199 FixRegisterBankingInFlow(PCFL(pcflow),0);
4200 BanksUsedFlow2(pcflow);
4202 continue; /* Don't need to check the flow from here - it's already been fixed */
4209 pcfl = setFirstItem(PCFL(pcflow)->to);
4212 pc = PCODE(pcfl->pcflow);
4214 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4215 pc->print(stderr,pc);
4218 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4221 pcfl=setNextItem(PCFL(pcflow)->to);
4224 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4225 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4227 FixRegisterBankingInFlow(PCFL(pcflow),0);
4228 BanksUsedFlow2(pcflow);
4233 Loop through the flow objects again and find the ones with the
4237 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4239 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4241 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4242 pcflow_max_To = pcflow;
4244 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4245 pcflow_max_From = pcflow;
4249 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4250 PCFL(pcflow_max_To)->pc.seq,
4251 PCFL(pcflow_max_To)->ToConflicts);
4254 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4255 PCFL(pcflow_max_From)->pc.seq,
4256 PCFL(pcflow_max_From)->FromConflicts);
4260 /*-----------------------------------------------------------------*/
4261 /*-----------------------------------------------------------------*/
4262 void DumpFlow(pBlock *pb)
4266 pCodeFlowLink *pcfl;
4269 fprintf(stderr,"Dump flow \n");
4270 pb->pcHead->print(stderr, pb->pcHead);
4272 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4273 pcflow->print(stderr,pcflow);
4275 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4277 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4279 if(!isPCFL(pcflow)) {
4280 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4283 fprintf(stderr,"dumping: ");
4284 pcflow->print(stderr,pcflow);
4285 FlowStats(PCFL(pcflow));
4287 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4289 pc = PCODE(pcfl->pcflow);
4291 fprintf(stderr, " from seq %d:\n",pc->seq);
4293 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4294 pc->print(stderr,pc);
4299 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4301 pc = PCODE(pcfl->pcflow);
4303 fprintf(stderr, " to seq %d:\n",pc->seq);
4305 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4306 pc->print(stderr,pc);
4315 /*-----------------------------------------------------------------*/
4316 /*-----------------------------------------------------------------*/
4317 int OptimizepBlock(pBlock *pb)
4322 if(!pb || !peepOptimizing)
4325 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4327 for(pc = pb->pcHead; pc; pc = pc->next)
4328 matches += pCodePeepMatchRule(pc);
4331 pc = findNextInstruction(pb->pcHead);
4339 if(pCodePeepMatchRule(pc)) {
4344 pc = findNextInstruction(pcprev->next);
4346 pc = findNextInstruction(pb->pcHead);
4348 pc = findNextInstruction(pc->next);
4352 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4357 /*-----------------------------------------------------------------*/
4358 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4359 /*-----------------------------------------------------------------*/
4360 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4364 for(pc = pcs; pc; pc = pc->next) {
4366 if((pc->type == PC_OPCODE) &&
4368 (PCI(pc)->pcop->type == PO_LABEL) &&
4369 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4377 /*-----------------------------------------------------------------*/
4378 /*-----------------------------------------------------------------*/
4379 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4386 (PCI(pc)->pcop->type == PO_LABEL)) {
4388 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4390 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4392 free(pcol->pcop.name);
4394 /* If the key is negative, then we (probably) have a label to
4395 * a function and the name is already defined */
4398 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4402 //sprintf(buffer,"_%05d_DS_",pcl->key);
4404 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4406 pcol->pcop.name = Safe_strdup(s);
4407 pcol->key = pcl->key;
4408 //pc->print(stderr,pc);
4415 /*-----------------------------------------------------------------*/
4416 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4417 /* pCode chain if they're not used. */
4418 /*-----------------------------------------------------------------*/
4419 void pBlockRemoveUnusedLabels(pBlock *pb)
4421 pCode *pc; pCodeLabel *pcl;
4426 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4428 pBranch *pbr = PCI(pc)->label;
4429 if(pbr && pbr->next) {
4430 pCode *pcd = pb->pcHead;
4432 //fprintf(stderr, "multiple labels\n");
4433 //pc->print(stderr,pc);
4438 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4439 //fprintf(stderr,"Used by:\n");
4440 //pcd->print(stderr,pcd);
4442 exchangeLabels(PCL(pbr->pc),pcd);
4451 for(pc = pb->pcHead; pc; pc = pc->next) {
4453 if(isPCL(pc)) // pc->type == PC_LABEL)
4455 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4456 pcl = PCL(PCI(pc)->label->pc);
4459 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4461 /* This pCode is a label, so search the pBlock to see if anyone
4464 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4465 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4466 /* Couldn't find an instruction that refers to this label
4467 * So, unlink the pCode label from it's pCode chain
4468 * and destroy the label */
4469 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4471 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4472 if(pc->type == PC_LABEL) {
4474 pCodeLabelDestruct(pc);
4476 unlinkpCodeFromBranch(pc, PCODE(pcl));
4477 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4488 /*-----------------------------------------------------------------*/
4489 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4490 /* chain and put them into pBranches that are */
4491 /* associated with the appropriate pCode */
4493 /*-----------------------------------------------------------------*/
4494 void pBlockMergeLabels(pBlock *pb)
4497 pCode *pc, *pcnext=NULL;
4502 /* First, Try to remove any unused labels */
4503 //pBlockRemoveUnusedLabels(pb);
4505 /* Now loop through the pBlock and merge the labels with the opcodes */
4508 // for(pc = pb->pcHead; pc; pc = pc->next) {
4511 pCode *pcn = pc->next;
4513 if(pc->type == PC_LABEL) {
4515 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4516 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4517 if((pcnext = findNextInstruction(pc) )) {
4519 // Unlink the pCode label from it's pCode chain
4522 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4523 // And link it into the instruction's pBranch labels. (Note, since
4524 // it's possible to have multiple labels associated with one instruction
4525 // we must provide a means to accomodate the additional labels. Thus
4526 // the labels are placed into the singly-linked list "label" as
4527 // opposed to being a single member of the pCodeInstruction.)
4529 //_ALLOC(pbr,sizeof(pBranch));
4530 pbr = Safe_calloc(1,sizeof(pBranch));
4534 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4537 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4539 } else if(pc->type == PC_CSOURCE) {
4541 /* merge the source line symbolic info into the next instruction */
4542 if((pcnext = findNextInstruction(pc) )) {
4544 // Unlink the pCode label from it's pCode chain
4546 PCI(pcnext)->cline = PCCS(pc);
4547 //fprintf(stderr, "merging CSRC\n");
4548 //genericPrint(stderr,pcnext);
4554 pBlockRemoveUnusedLabels(pb);
4558 /*-----------------------------------------------------------------*/
4559 /*-----------------------------------------------------------------*/
4560 int OptimizepCode(char dbName)
4562 #define MAX_PASSES 4
4571 DFPRINTF((stderr," Optimizing pCode\n"));
4575 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4576 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4577 matches += OptimizepBlock(pb);
4580 while(matches && ++passes < MAX_PASSES);
4585 /*-----------------------------------------------------------------*/
4586 /* popCopyGPR2Bit - copy a pcode operator */
4587 /*-----------------------------------------------------------------*/
4589 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4593 pcop = newpCodeOpBit(pc->name, bitval, 0);
4595 if( !( (pcop->type == PO_LABEL) ||
4596 (pcop->type == PO_LITERAL) ||
4597 (pcop->type == PO_STR) ))
4598 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4606 /*-----------------------------------------------------------------*/
4607 /*-----------------------------------------------------------------*/
4608 int InstructionRegBank(pCode *pc)
4612 if( (reg = getRegFromInstruction(pc)) == NULL)
4615 return REG_BANK(reg);
4620 /*-----------------------------------------------------------------*/
4621 /*-----------------------------------------------------------------*/
4622 void FixRegisterBanking(pBlock *pb)
4633 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4634 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4637 /* loop through all of the flow blocks with in one pblock */
4639 //fprintf(stderr,"Register banking\n");
4642 /* at this point, pc should point to a PC_FLOW object */
4645 /* for each flow block, determine the register banking
4650 //genericPrint(stderr, pc);
4652 reg = getRegFromInstruction(pc);
4655 fprintf(stderr, " %s ",reg->name);
4656 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4657 reg->address,REG_BANK(reg),reg->isBitField);
4662 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4663 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4667 /* Examine the instruction before this one to make sure it is
4668 * not a skip type instruction */
4669 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4671 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4675 reg_bank = (reg) ? REG_BANK(reg) : 0;
4677 b = cur_bank ^ reg_bank;
4679 cur_bank = reg_bank;
4684 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4687 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4688 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4692 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4693 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4695 insertBankSwitch(0, pc, -1, -1);
4701 //fprintf(stderr, "Bummer can't switch banks\n");
4711 // } while(pc && !(isPCFL(pc)));
4716 if(pcprev && cur_bank) {
4718 int pos = 1; /* Assume that the bank swithc instruction(s)
4719 * are inserted after this instruction */
4721 if((PCI(pcprev)->op == POC_RETLW) ||
4722 (PCI(pcprev)->op == POC_RETURN) ||
4723 (PCI(pcprev)->op == POC_RETFIE)) {
4725 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4731 /* Brute force - make sure that we point to bank 0 at the
4732 * end of each flow block */
4734 switch(cur_bank & 3) {
4738 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4741 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4742 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4745 insertBankSwitch(pos, pcprev, -1, -1);
4750 new_pc = newpCode(POC_BCF,
4751 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4752 pCodeInsertAfter(pcprev, new_pc);
4755 //fprintf(stderr, "Brute force switch\n");
4764 if(reg && REG_BANK(reg)!=cur_bank) {
4765 //fprintf(stderr,"need to switch banks\n");
4766 /* Examine the instruction before this one to make sure it is
4767 * not a skip type instruction */
4768 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4769 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4770 int b = cur_bank ^ REG_BANK(reg);
4772 cur_bank = REG_BANK(reg);
4778 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4781 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4782 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4786 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4787 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4789 insertBankSwitch(0, pc, -1, -1);
4798 void pBlockDestruct(pBlock *pb)
4809 /*-----------------------------------------------------------------*/
4810 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4811 /* name dbName and combine them */
4812 /* into one block */
4813 /*-----------------------------------------------------------------*/
4814 void mergepBlocks(char dbName)
4817 pBlock *pb, *pbmerged = NULL,*pbn;
4819 pb = the_pFile->pbHead;
4821 //fprintf(stderr," merging blocks named %c\n",dbName);
4825 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4826 if( getpBlock_dbName(pb) == dbName) {
4828 //fprintf(stderr," merged block %c\n",dbName);
4833 addpCode2pBlock(pbmerged, pb->pcHead);
4834 /* addpCode2pBlock doesn't handle the tail: */
4835 pbmerged->pcTail = pb->pcTail;
4837 pb->prev->next = pbn;
4839 pbn->prev = pb->prev;
4844 //printpBlock(stderr, pbmerged);
4851 /*-----------------------------------------------------------------*/
4852 /* AnalyzeFlow - Examine the flow of the code and optimize */
4854 /* level 0 == minimal optimization */
4855 /* optimize registers that are used only by two instructions */
4856 /* level 1 == maximal optimization */
4857 /* optimize by looking at pairs of instructions that use the */
4859 /*-----------------------------------------------------------------*/
4861 void AnalyzeFlow(int level)
4863 static int times_called=0;
4871 /* if this is not the first time this function has been called,
4872 then clean up old flow information */
4873 if(times_called++) {
4874 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4877 RegsUnMapLiveRanges();
4883 /* Phase 2 - Flow Analysis - Register Banking
4885 * In this phase, the individual flow blocks are examined
4886 * and register banking is fixed.
4889 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4890 //FixRegisterBanking(pb);
4892 /* Phase 2 - Flow Analysis
4894 * In this phase, the pCode is partition into pCodeFlow
4895 * blocks. The flow blocks mark the points where a continuous
4896 * stream of instructions changes flow (e.g. because of
4897 * a call or goto or whatever).
4900 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4904 /* Phase 2 - Flow Analysis - linking flow blocks
4906 * In this phase, the individual flow blocks are examined
4907 * to determine their order of excution.
4910 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4913 /* Phase 3 - Flow Analysis - Flow Tree
4915 * In this phase, the individual flow blocks are examined
4916 * to determine their order of excution.
4919 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4923 /* Phase x - Flow Analysis - Used Banks
4925 * In this phase, the individual flow blocks are examined
4926 * to determine the Register Banks they use
4929 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4933 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4934 pCodeRegMapLiveRanges(pb);
4936 RemoveUnusedRegisters();
4938 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4939 pCodeRegOptimizeRegUsage(level);
4945 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4949 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4951 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4952 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4953 pcflow = pcflow->next) {
4955 FillFlow(PCFL(pcflow));
4960 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4962 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4963 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4964 pcflow = pcflow->next) {
4966 FlowStats(PCFL(pcflow));
4972 /*-----------------------------------------------------------------*/
4973 /* AnalyzeBanking - Called after the memory addresses have been */
4974 /* assigned to the registers. */
4976 /*-----------------------------------------------------------------*/
4978 void AnalyzeBanking(void)
4982 if(!picIsInitialized()) {
4983 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4984 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4985 fprintf(stderr,"support/scripts/inc2h.pl\n");
4986 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4991 /* Phase x - Flow Analysis - Used Banks
4993 * In this phase, the individual flow blocks are examined
4994 * to determine the Register Banks they use
5000 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5002 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5003 FixRegisterBanking(pb);
5007 // Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused.
5010 /*-----------------------------------------------------------------*/
5011 /*-----------------------------------------------------------------*/
5012 DEFSETFUNC (resetrIdx)
5014 if (!((regs *)item)->isFixed)
5015 ((regs *)item)->rIdx = 0;
5020 pCode *findFunction(char *fname);
5022 /*-----------------------------------------------------------------*/
5023 /*-----------------------------------------------------------------*/
5024 unsigned register_reassign(pBlock *pb, unsigned idx)
5028 /* check recursion */
5029 pc = setFirstItem(pb->function_entries);
5033 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5035 if (pb->tregisters) {
5037 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5038 if (r->type == REG_GPR) {
5040 if (r->rIdx < (int)idx) {
5043 sprintf(s,"r0x%02X", r->rIdx);
5044 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5046 r->name = Safe_strdup(s);
5052 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5054 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5055 char *dest = get_op_from_instruction(PCI(pc));
5057 pCode *pcn = findFunction(dest);
5059 register_reassign(pcn->pb,idx);
5068 /*-----------------------------------------------------------------*/
5069 /* Re-allocate the GPR for optimum reuse for a given pblock */
5070 /* eg if a function m() calls function f1() and f2(), where f1 */
5071 /* allocates a local variable vf1 and f2 allocates a local */
5072 /* variable vf2. Then providing f1 and f2 do not call each other */
5073 /* they may share the same general purpose registers for vf1 and */
5075 /* This is done by first setting the the regs rIdx to start after */
5076 /* all the global variables, then walking through the call tree */
5077 /* renaming the registers to match their new idx and incrementng */
5078 /* it as it goes. If a function has already been called it will */
5079 /* only rename the registers if it has already used up those */
5080 /* registers ie rIdx of the function's registers is lower than the */
5081 /* current rIdx. That way the register will not be reused while */
5082 /* still being used by an eariler function call. */
5083 /*-----------------------------------------------------------------*/
5084 void register_reusage(pBlock *mainPb)
5086 static int exercised = 0;
5087 if (!exercised) { /* Only do this once */
5088 /* Find end of statically allocated variables for start idx */
5089 unsigned idx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5091 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5092 if (r->type != REG_SFR) {
5093 idx += r->size; /* Increment for all statically allocated variables */
5097 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5100 idx = register_reassign(mainPb,idx); /* Do main and all the functions that are called from it. */
5101 idx = register_reassign(the_pFile->pbHead,idx); /* Do the other functions such as interrupts. */
5107 /*-----------------------------------------------------------------*/
5108 /* buildCallTree - look at the flow and extract all of the calls */
5110 /*-----------------------------------------------------------------*/
5111 set *register_usage(pBlock *pb);
5114 void buildCallTree(void )
5117 pBlock *pb, *mainPb = 0;
5123 /* Now build the call tree.
5124 First we examine all of the pCodes for functions.
5125 Keep in mind that the function boundaries coincide
5126 with pBlock boundaries.
5128 The algorithm goes something like this:
5129 We have two nested loops. The outer loop iterates
5130 through all of the pBlocks/functions. The inner
5131 loop iterates through all of the pCodes for
5132 a given pBlock. When we begin iterating through
5133 a pBlock, the variable pc_fstart, pCode of the start
5134 of a function, is cleared. We then search for pCodes
5135 of type PC_FUNCTION. When one is encountered, we
5136 initialize pc_fstart to this and at the same time
5137 associate a new pBranch object that signifies a
5138 branch entry. If a return is found, then this signifies
5139 a function exit point. We'll link the pCodes of these
5140 returns to the matching pc_fstart.
5142 When we're done, a doubly linked list of pBranches
5143 will exist. The head of this list is stored in
5144 `the_pFile', which is the meta structure for all
5145 of the pCode. Look at the printCallTree function
5146 on how the pBranches are linked together.
5149 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5150 pCode *pc_fstart=NULL;
5151 for(pc = pb->pcHead; pc; pc = pc->next) {
5153 pCodeFunction *pcf = PCF(pc);
5156 if(STRCASECMP(pcf->fname, "_main") == 0) {
5157 //fprintf(stderr," found main \n");
5158 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5163 pbr = Safe_calloc(1,sizeof(pBranch));
5164 pbr->pc = pc_fstart = pc;
5167 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5169 // Here's a better way of doing the same:
5170 addSet(&pb->function_entries, pc);
5173 // Found an exit point in a function, e.g. return
5174 // (Note, there may be more than one return per function)
5176 pBranchLink(PCF(pc_fstart), pcf);
5178 addSet(&pb->function_exits, pc);
5180 } else if(isCALL(pc)) {
5181 addSet(&pb->function_calls,pc);
5187 register_reusage(mainPb); /* Comment out this line to prevent local function registers being reused. Note from this point onwards finding a GPR by its rIdx value will no longer work.*/
5190 /* Re-allocate the registers so that there are no collisions
5191 * between local variables when one function call another */
5194 // pic14_deallocateAllRegs();
5196 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5203 /*-----------------------------------------------------------------*/
5204 /* AnalyzepCode - parse the pCode that has been generated and form */
5205 /* all of the logical connections. */
5207 /* Essentially what's done here is that the pCode flow is */
5209 /*-----------------------------------------------------------------*/
5211 void AnalyzepCode(char dbName)
5222 /* Phase 1 - Register allocation and peep hole optimization
5224 * The first part of the analysis is to determine the registers
5225 * that are used in the pCode. Once that is done, the peep rules
5226 * are applied to the code. We continue to loop until no more
5227 * peep rule optimizations are found (or until we exceed the
5228 * MAX_PASSES threshold).
5230 * When done, the required registers will be determined.
5236 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5237 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5239 /* First, merge the labels with the instructions */
5240 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5241 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5243 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5244 //fprintf(stderr," analyze and merging block %c\n",dbName);
5245 pBlockMergeLabels(pb);
5248 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5252 changes = OptimizepCode(dbName);
5254 } while(changes && (i++ < MAX_PASSES));
5259 /*-----------------------------------------------------------------*/
5260 /* ispCodeFunction - returns true if *pc is the pCode of a */
5262 /*-----------------------------------------------------------------*/
5263 bool ispCodeFunction(pCode *pc)
5266 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5272 /*-----------------------------------------------------------------*/
5273 /* findFunction - Search for a function by name (given the name) */
5274 /* in the set of all functions that are in a pBlock */
5275 /* (note - I expect this to change because I'm planning to limit */
5276 /* pBlock's to just one function declaration */
5277 /*-----------------------------------------------------------------*/
5278 pCode *findFunction(char *fname)
5285 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5287 pc = setFirstItem(pb->function_entries);
5290 if((pc->type == PC_FUNCTION) &&
5292 (strcmp(fname, PCF(pc)->fname)==0))
5295 pc = setNextItem(pb->function_entries);
5303 void MarkUsedRegisters(set *regset)
5308 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5309 r2 = pic14_regWithIdx(r1->rIdx);
5315 void pBlockStats(FILE *of, pBlock *pb)
5321 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5323 // for now just print the first element of each set
5324 pc = setFirstItem(pb->function_entries);
5326 fprintf(of,";entry: ");
5329 pc = setFirstItem(pb->function_exits);
5331 fprintf(of,";has an exit\n");
5335 pc = setFirstItem(pb->function_calls);
5337 fprintf(of,";functions called:\n");
5340 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5341 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5343 pc = setNextItem(pb->function_calls);
5347 r = setFirstItem(pb->tregisters);
5349 int n = elementsInSet(pb->tregisters);
5351 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5354 fprintf(of,"; %s\n",r->name);
5355 r = setNextItem(pb->tregisters);
5360 /*-----------------------------------------------------------------*/
5361 /*-----------------------------------------------------------------*/
5363 static void sequencepCode(void)
5369 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5371 pb->seq = GpCodeSequenceNumber+1;
5373 for( pc = pb->pcHead; pc; pc = pc->next)
5374 pc->seq = ++GpCodeSequenceNumber;
5380 /*-----------------------------------------------------------------*/
5381 /*-----------------------------------------------------------------*/
5382 set *register_usage(pBlock *pb)
5385 set *registers=NULL;
5386 set *registersInCallPath = NULL;
5388 /* check recursion */
5390 pc = setFirstItem(pb->function_entries);
5397 if(pc->type != PC_FUNCTION)
5398 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5400 pc = setFirstItem(pb->function_calls);
5401 for( ; pc; pc = setNextItem(pb->function_calls)) {
5403 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5404 char *dest = get_op_from_instruction(PCI(pc));
5406 pcn = findFunction(dest);
5408 registersInCallPath = register_usage(pcn->pb);
5410 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5415 pBlockStats(stderr,pb); // debug
5418 // Mark the registers in this block as used.
5420 MarkUsedRegisters(pb->tregisters);
5421 if(registersInCallPath) {
5422 /* registers were used in the functions this pBlock has called */
5423 /* so now, we need to see if these collide with the ones we are */
5426 regs *r1,*r2, *newreg;
5428 DFPRINTF((stderr,"comparing registers\n"));
5430 r1 = setFirstItem(registersInCallPath);
5433 r2 = setFirstItem(pb->tregisters);
5435 while(r2 && (r1->type != REG_STK)) {
5437 if(r2->rIdx == r1->rIdx) {
5438 newreg = pic14_findFreeReg(REG_GPR);
5442 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5446 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5447 r1->rIdx, newreg->rIdx));
5448 r2->rIdx = newreg->rIdx;
5449 //if(r2->name) free(r2->name);
5451 r2->name = Safe_strdup(newreg->name);
5455 newreg->wasUsed = 1;
5457 r2 = setNextItem(pb->tregisters);
5460 r1 = setNextItem(registersInCallPath);
5463 /* Collisions have been resolved. Now free the registers in the call path */
5464 r1 = setFirstItem(registersInCallPath);
5466 if(r1->type != REG_STK) {
5467 newreg = pic14_regWithIdx(r1->rIdx);
5470 r1 = setNextItem(registersInCallPath);
5474 // MarkUsedRegisters(pb->registers);
5476 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5479 DFPRINTF((stderr,"returning regs\n"));
5481 DFPRINTF((stderr,"not returning regs\n"));
5483 DFPRINTF((stderr,"pBlock after register optim.\n"));
5484 pBlockStats(stderr,pb); // debug
5490 /*-----------------------------------------------------------------*/
5491 /* printCallTree - writes the call tree to a file */
5493 /*-----------------------------------------------------------------*/
5494 void pct2(FILE *of,pBlock *pb,int indent)
5498 // set *registersInCallPath = NULL;
5504 return; //recursion ?
5506 pc = setFirstItem(pb->function_entries);
5513 for(i=0;i<indent;i++) // Indentation
5516 if(pc->type == PC_FUNCTION)
5517 fprintf(of,"%s\n",PCF(pc)->fname);
5522 pc = setFirstItem(pb->function_calls);
5523 for( ; pc; pc = setNextItem(pb->function_calls)) {
5525 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5526 char *dest = get_op_from_instruction(PCI(pc));
5528 pcn = findFunction(dest);
5530 pct2(of,pcn->pb,indent+1);
5532 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5540 /*-----------------------------------------------------------------*/
5541 /* printCallTree - writes the call tree to a file */
5543 /*-----------------------------------------------------------------*/
5545 void printCallTree(FILE *of)
5557 fprintf(of, "\npBlock statistics\n");
5558 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5563 fprintf(of,"Call Tree\n");
5564 pbr = the_pFile->functions;
5568 if(!ispCodeFunction(pc))
5569 fprintf(of,"bug in call tree");
5572 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5574 while(pc->next && !ispCodeFunction(pc->next)) {
5576 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5577 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5585 fprintf(of,"\n**************\n\na better call tree\n");
5586 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5591 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5592 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5598 /*-----------------------------------------------------------------*/
5600 /*-----------------------------------------------------------------*/
5602 void InlineFunction(pBlock *pb)
5610 pc = setFirstItem(pb->function_calls);
5612 for( ; pc; pc = setNextItem(pb->function_calls)) {
5615 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5621 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5623 //fprintf(stderr,"Cool can inline:\n");
5624 //pcn->print(stderr,pcn);
5626 //fprintf(stderr,"recursive call Inline\n");
5627 InlineFunction(pcn->pb);
5628 //fprintf(stderr,"return from recursive call Inline\n");
5631 At this point, *pc points to a CALL mnemonic, and
5632 *pcn points to the function that is being called.
5634 To in-line this call, we need to remove the CALL
5635 and RETURN(s), and link the function pCode in with
5641 /* Remove the CALL */
5645 /* remove callee pBlock from the pBlock linked list */
5646 removepBlock(pcn->pb);
5654 /* Remove the Function pCode */
5655 pct = findNextInstruction(pcn->next);
5657 /* Link the function with the callee */
5658 pc->next = pcn->next;
5659 pcn->next->prev = pc;
5661 /* Convert the function name into a label */
5663 pbr = Safe_calloc(1,sizeof(pBranch));
5664 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5666 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5667 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5669 /* turn all of the return's except the last into goto's */
5670 /* check case for 2 instruction pBlocks */
5671 pce = findNextInstruction(pcn->next);
5673 pCode *pce_next = findNextInstruction(pce->next);
5675 if(pce_next == NULL) {
5676 /* found the last return */
5677 pCode *pc_call_next = findNextInstruction(pc_call->next);
5679 //fprintf(stderr,"found last return\n");
5680 //pce->print(stderr,pce);
5681 pce->prev->next = pc_call->next;
5682 pc_call->next->prev = pce->prev;
5683 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5693 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5699 /*-----------------------------------------------------------------*/
5701 /*-----------------------------------------------------------------*/
5703 void InlinepCode(void)
5712 if(!functionInlining)
5715 /* Loop through all of the function definitions and count the
5716 * number of times each one is called */
5717 //fprintf(stderr,"inlining %d\n",__LINE__);
5719 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5721 pc = setFirstItem(pb->function_calls);
5723 for( ; pc; pc = setNextItem(pb->function_calls)) {
5726 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5727 if(pcn && isPCF(pcn)) {
5728 PCF(pcn)->ncalled++;
5731 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5736 //fprintf(stderr,"inlining %d\n",__LINE__);
5738 /* Now, Loop through the function definitions again, but this
5739 * time inline those functions that have only been called once. */
5741 InlineFunction(the_pFile->pbHead);
5742 //fprintf(stderr,"inlining %d\n",__LINE__);
5744 for(pb = the_pFile->pbHead; pb; pb = pb->next)