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};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
78 int debug_verbose = 1; /* Set true to inundate .asm file */
80 // static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
87 extern int picIsInitialized(void);
89 /****************************************************************/
90 /* Forward declarations */
91 /****************************************************************/
93 void unlinkpCode(pCode *pc);
95 static void genericAnalyze(pCode *pc);
96 static void AnalyzeGOTO(pCode *pc);
97 static void AnalyzeSKIP(pCode *pc);
98 static void AnalyzeRETURN(pCode *pc);
101 static void genericDestruct(pCode *pc);
102 static void genericPrint(FILE *of,pCode *pc);
104 static void pCodePrintLabel(FILE *of, pCode *pc);
105 static void pCodePrintFunction(FILE *of, pCode *pc);
106 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
107 static char *get_op_from_instruction( pCodeInstruction *pcc);
108 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
109 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
110 int pCodePeepMatchRule(pCode *pc);
111 void pBlockStats(FILE *of, pBlock *pb);
112 pBlock *newpBlock(void);
113 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
114 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
115 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
116 void pCodeRegMapLiveRanges(pBlock *pb);
119 /****************************************************************/
120 /* PIC Instructions */
121 /****************************************************************/
123 pCodeInstruction pciADDWF = {
124 {PC_OPCODE, NULL, NULL, 0, NULL,
137 1,0, // dest, bit instruction
139 0, // literal operand
141 (PCC_W | PCC_REGISTER), // inCond
142 (PCC_REGISTER | PCC_Z) // outCond
145 pCodeInstruction pciADDFW = {
146 {PC_OPCODE, NULL, NULL, 0, NULL,
159 0,0, // dest, bit instruction
161 0, // literal operand
163 (PCC_W | PCC_REGISTER), // inCond
164 (PCC_W | PCC_Z) // outCond
167 pCodeInstruction pciADDLW = {
168 {PC_OPCODE, NULL, NULL, 0, NULL,
181 0,0, // dest, bit instruction
183 1, // literal operand
185 (PCC_W | PCC_LITERAL), // inCond
186 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
189 pCodeInstruction pciANDLW = {
190 {PC_OPCODE, NULL, NULL, 0, NULL,
203 0,0, // dest, bit instruction
205 1, // literal operand
207 (PCC_W | PCC_LITERAL), // inCond
208 (PCC_W | PCC_Z) // outCond
211 pCodeInstruction pciANDWF = {
212 {PC_OPCODE, NULL, NULL, 0, NULL,
225 1,0, // dest, bit instruction
227 0, // literal operand
229 (PCC_W | PCC_REGISTER), // inCond
230 (PCC_REGISTER | PCC_Z) // outCond
233 pCodeInstruction pciANDFW = {
234 {PC_OPCODE, NULL, NULL, 0, NULL,
247 0,0, // dest, bit instruction
249 0, // literal operand
251 (PCC_W | PCC_REGISTER), // inCond
252 (PCC_W | PCC_Z) // outCond
255 pCodeInstruction pciBCF = {
256 {PC_OPCODE, NULL, NULL, 0, NULL,
269 1,1, // dest, bit instruction
271 0, // literal operand
273 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
274 PCC_REGISTER // outCond
277 pCodeInstruction pciBSF = {
278 {PC_OPCODE, NULL, NULL, 0, NULL,
291 1,1, // dest, bit instruction
293 0, // literal operand
295 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
296 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
299 pCodeInstruction pciBTFSC = {
300 {PC_OPCODE, NULL, NULL, 0, NULL,
313 0,1, // dest, bit instruction
315 0, // literal operand
317 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
318 PCC_EXAMINE_PCOP // outCond
321 pCodeInstruction pciBTFSS = {
322 {PC_OPCODE, NULL, NULL, 0, NULL,
335 0,1, // dest, bit instruction
337 0, // literal operand
339 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
340 PCC_EXAMINE_PCOP // outCond
343 pCodeInstruction pciCALL = {
344 {PC_OPCODE, NULL, NULL, 0, NULL,
357 0,0, // dest, bit instruction
359 0, // literal operand
365 pCodeInstruction pciCOMF = {
366 {PC_OPCODE, NULL, NULL, 0, NULL,
379 1,0, // dest, bit instruction
381 0, // literal operand
383 PCC_REGISTER, // inCond
384 PCC_REGISTER // outCond
387 pCodeInstruction pciCOMFW = {
388 {PC_OPCODE, NULL, NULL, 0, NULL,
401 0,0, // dest, bit instruction
403 0, // literal operand
405 PCC_REGISTER, // inCond
409 pCodeInstruction pciCLRF = {
410 {PC_OPCODE, NULL, NULL, 0, NULL,
423 0,0, // dest, bit instruction
425 0, // literal operand
428 PCC_REGISTER // outCond
431 pCodeInstruction pciCLRW = {
432 {PC_OPCODE, NULL, NULL, 0, NULL,
445 0,0, // dest, bit instruction
447 0, // literal operand
453 pCodeInstruction pciCLRWDT = {
454 {PC_OPCODE, NULL, NULL, 0, NULL,
467 0,0, // dest, bit instruction
469 0, // literal operand
475 pCodeInstruction pciDECF = {
476 {PC_OPCODE, NULL, NULL, 0, NULL,
489 1,0, // dest, bit instruction
491 0, // literal operand
493 PCC_REGISTER, // inCond
494 PCC_REGISTER // outCond
497 pCodeInstruction pciDECFW = {
498 {PC_OPCODE, NULL, NULL, 0, NULL,
511 0,0, // dest, bit instruction
513 0, // literal operand
515 PCC_REGISTER, // inCond
519 pCodeInstruction pciDECFSZ = {
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 1,0, // dest, bit instruction
535 0, // literal operand
537 PCC_REGISTER, // inCond
538 PCC_REGISTER // outCond
541 pCodeInstruction pciDECFSZW = {
542 {PC_OPCODE, NULL, NULL, 0, NULL,
555 0,0, // dest, bit instruction
557 0, // literal operand
559 PCC_REGISTER, // inCond
563 pCodeInstruction pciGOTO = {
564 {PC_OPCODE, NULL, NULL, 0, NULL,
577 0,0, // dest, bit instruction
579 0, // literal operand
585 pCodeInstruction pciINCF = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 1,0, // dest, bit instruction
601 0, // literal operand
603 PCC_REGISTER, // inCond
604 PCC_REGISTER // outCond
607 pCodeInstruction pciINCFW = {
608 {PC_OPCODE, NULL, NULL, 0, NULL,
621 0,0, // dest, bit instruction
623 0, // literal operand
625 PCC_REGISTER, // inCond
629 pCodeInstruction pciINCFSZ = {
630 {PC_OPCODE, NULL, NULL, 0, NULL,
643 1,0, // dest, bit instruction
645 0, // literal operand
647 PCC_REGISTER, // inCond
648 PCC_REGISTER // outCond
651 pCodeInstruction pciINCFSZW = {
652 {PC_OPCODE, NULL, NULL, 0, NULL,
665 0,0, // dest, bit instruction
667 0, // literal operand
669 PCC_REGISTER, // inCond
673 pCodeInstruction pciIORWF = {
674 {PC_OPCODE, NULL, NULL, 0, NULL,
687 1,0, // dest, bit instruction
689 0, // literal operand
691 (PCC_W | PCC_REGISTER), // inCond
692 (PCC_REGISTER | PCC_Z) // outCond
695 pCodeInstruction pciIORFW = {
696 {PC_OPCODE, NULL, NULL, 0, NULL,
709 0,0, // dest, bit instruction
711 0, // literal operand
713 (PCC_W | PCC_REGISTER), // inCond
714 (PCC_W | PCC_Z) // outCond
717 pCodeInstruction pciIORLW = {
718 {PC_OPCODE, NULL, NULL, 0, NULL,
731 0,0, // dest, bit instruction
733 1, // literal operand
735 (PCC_W | PCC_LITERAL), // inCond
736 (PCC_W | PCC_Z) // outCond
739 pCodeInstruction pciMOVF = {
740 {PC_OPCODE, NULL, NULL, 0, NULL,
753 1,0, // dest, bit instruction
755 0, // literal operand
757 PCC_REGISTER, // inCond
761 pCodeInstruction pciMOVFW = {
762 {PC_OPCODE, NULL, NULL, 0, NULL,
775 0,0, // dest, bit instruction
777 0, // literal operand
779 PCC_REGISTER, // inCond
780 (PCC_W | PCC_Z) // outCond
783 pCodeInstruction pciMOVWF = {
784 {PC_OPCODE, NULL, NULL, 0, NULL,
797 0,0, // dest, bit instruction
799 0, // literal operand
802 PCC_REGISTER // outCond
805 pCodeInstruction pciMOVLW = {
806 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 1, // literal operand
822 (PCC_NONE | PCC_LITERAL), // inCond
826 pCodeInstruction pciNOP = {
827 {PC_OPCODE, NULL, NULL, 0, NULL,
839 0,0, // dest, bit instruction
841 0, // literal operand
847 pCodeInstruction pciRETFIE = {
848 {PC_OPCODE, NULL, NULL, 0, NULL,
861 0,0, // dest, bit instruction
863 0, // literal operand
866 PCC_NONE // outCond (not true... affects the GIE bit too)
869 pCodeInstruction pciRETLW = {
870 {PC_OPCODE, NULL, NULL, 0, NULL,
883 0,0, // dest, bit instruction
885 1, // literal operand
887 PCC_LITERAL, // inCond
891 pCodeInstruction pciRETURN = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
905 0,0, // dest, bit instruction
907 0, // literal operand
913 pCodeInstruction pciRLF = {
914 {PC_OPCODE, NULL, NULL, 0, NULL,
927 1,0, // dest, bit instruction
929 0, // literal operand
931 (PCC_C | PCC_REGISTER), // inCond
932 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
935 pCodeInstruction pciRLFW = {
936 {PC_OPCODE, NULL, NULL, 0, NULL,
949 0,0, // dest, bit instruction
951 0, // literal operand
953 (PCC_C | PCC_REGISTER), // inCond
954 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
957 pCodeInstruction pciRRF = {
958 {PC_OPCODE, NULL, NULL, 0, NULL,
971 1,0, // dest, bit instruction
973 0, // literal operand
975 (PCC_C | PCC_REGISTER), // inCond
976 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
979 pCodeInstruction pciRRFW = {
980 {PC_OPCODE, NULL, NULL, 0, NULL,
993 0,0, // dest, bit instruction
995 0, // literal operand
997 (PCC_C | PCC_REGISTER), // inCond
998 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1001 pCodeInstruction pciSUBWF = {
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1008 NULL, // from branch
1015 1,0, // dest, bit instruction
1016 0,0, // branch, skip
1017 0, // literal operand
1019 (PCC_W | PCC_REGISTER), // inCond
1020 (PCC_REGISTER | PCC_Z) // outCond
1023 pCodeInstruction pciSUBFW = {
1024 {PC_OPCODE, NULL, NULL, 0, NULL,
1030 NULL, // from branch
1037 0,0, // dest, bit instruction
1038 0,0, // branch, skip
1039 0, // literal operand
1041 (PCC_W | PCC_REGISTER), // inCond
1042 (PCC_W | PCC_Z) // outCond
1045 pCodeInstruction pciSUBLW = {
1046 {PC_OPCODE, NULL, NULL, 0, NULL,
1052 NULL, // from branch
1059 0,0, // dest, bit instruction
1060 0,0, // branch, skip
1061 1, // literal operand
1063 (PCC_W | PCC_LITERAL), // inCond
1064 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1067 pCodeInstruction pciSWAPF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1085 (PCC_REGISTER), // inCond
1086 (PCC_REGISTER) // outCond
1089 pCodeInstruction pciSWAPFW = {
1090 {PC_OPCODE, NULL, NULL, 0, NULL,
1096 NULL, // from branch
1103 0,0, // dest, bit instruction
1104 0,0, // branch, skip
1105 0, // literal operand
1107 (PCC_REGISTER), // inCond
1111 pCodeInstruction pciTRIS = {
1112 {PC_OPCODE, NULL, NULL, 0, NULL,
1118 NULL, // from branch
1125 0,0, // dest, bit instruction
1126 0,0, // branch, skip
1127 0, // literal operand
1130 PCC_REGISTER // outCond
1133 pCodeInstruction pciXORWF = {
1134 {PC_OPCODE, NULL, NULL, 0, NULL,
1140 NULL, // from branch
1147 1,0, // dest, bit instruction
1148 0,0, // branch, skip
1149 0, // literal operand
1151 (PCC_W | PCC_REGISTER), // inCond
1152 (PCC_REGISTER | PCC_Z) // outCond
1155 pCodeInstruction pciXORFW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1162 NULL, // from branch
1169 0,0, // dest, bit instruction
1170 0,0, // branch, skip
1171 0, // literal operand
1173 (PCC_W | PCC_REGISTER), // inCond
1174 (PCC_W | PCC_Z) // outCond
1177 pCodeInstruction pciXORLW = {
1178 {PC_OPCODE, NULL, NULL, 0, NULL,
1184 NULL, // from branch
1191 0,0, // dest, bit instruction
1192 0,0, // branch, skip
1193 1, // literal operand
1195 (PCC_W | PCC_LITERAL), // inCond
1196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1200 #define MAX_PIC14MNEMONICS 100
1201 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1204 #ifdef HAVE_VSNPRINTF
1205 // Alas, vsnprintf is not ANSI standard, and does not exist
1206 // on Solaris (and probably other non-Gnu flavored Unixes).
1208 /*-----------------------------------------------------------------*/
1209 /* SAFE_snprintf - like snprintf except the string pointer is */
1210 /* after the string has been printed to. This is */
1211 /* useful for printing to string as though if it */
1212 /* were a stream. */
1213 /*-----------------------------------------------------------------*/
1214 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1222 va_start(val, format);
1224 vsnprintf(*str, *size, format, val);
1230 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1231 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1239 #else // HAVE_VSNPRINTF
1241 // This version is *not* safe, despite the name.
1243 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1247 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1252 va_start(val, format);
1254 vsprintf(buffer, format, val);
1257 len = strlen(buffer);
1259 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1260 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1263 strcpy(*str, buffer);
1269 #endif // HAVE_VSNPRINTF
1272 extern void initStack(int base_address, int size);
1273 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1274 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1275 extern void init_pic(char *);
1277 void pCodeInitRegisters(void)
1279 static int initialized=0;
1285 initStack(0xfff, 8);
1286 init_pic(port->processor);
1288 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1289 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1290 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1291 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1292 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1293 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1295 pc_status.rIdx = IDX_STATUS;
1296 pc_fsr.rIdx = IDX_FSR;
1297 pc_indf.rIdx = IDX_INDF;
1298 pc_intcon.rIdx = IDX_INTCON;
1299 pc_pcl.rIdx = IDX_PCL;
1300 pc_pclath.rIdx = IDX_PCLATH;
1302 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1303 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1304 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1306 pc_kzero.rIdx = IDX_KZ;
1307 pc_wsave.rIdx = IDX_WSAVE;
1308 pc_ssave.rIdx = IDX_SSAVE;
1310 /* probably should put this in a separate initialization routine */
1311 pb_dead_pcodes = newpBlock();
1315 /*-----------------------------------------------------------------*/
1316 /* mnem2key - convert a pic mnemonic into a hash key */
1317 /* (BTW - this spreads the mnemonics quite well) */
1319 /*-----------------------------------------------------------------*/
1321 int mnem2key(char const *mnem)
1330 key += toupper(*mnem++) +1;
1334 return (key & 0x1f);
1338 void pic14initMnemonics(void)
1343 pCodeInstruction *pci;
1345 if(mnemonics_initialized)
1348 //FIXME - probably should NULL out the array before making the assignments
1349 //since we check the array contents below this initialization.
1351 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1352 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1353 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1354 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1355 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1356 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1357 pic14Mnemonics[POC_BCF] = &pciBCF;
1358 pic14Mnemonics[POC_BSF] = &pciBSF;
1359 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1360 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1361 pic14Mnemonics[POC_CALL] = &pciCALL;
1362 pic14Mnemonics[POC_COMF] = &pciCOMF;
1363 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1364 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1365 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1366 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1367 pic14Mnemonics[POC_DECF] = &pciDECF;
1368 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1369 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1370 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1371 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1372 pic14Mnemonics[POC_INCF] = &pciINCF;
1373 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1374 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1375 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1376 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1377 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1378 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1379 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1380 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1381 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1382 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1383 pic14Mnemonics[POC_NOP] = &pciNOP;
1384 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1385 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1386 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1387 pic14Mnemonics[POC_RLF] = &pciRLF;
1388 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1389 pic14Mnemonics[POC_RRF] = &pciRRF;
1390 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1391 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1392 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1393 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1394 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1395 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1396 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1397 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1398 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1399 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1401 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1402 if(pic14Mnemonics[i])
1403 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1404 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1407 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1408 pci = hTabNextItem(pic14MnemonicsHash, &key);
1411 mnemonics_initialized = 1;
1414 int getpCodePeepCommand(char *cmd);
1416 int getpCode(char *mnem,unsigned dest)
1419 pCodeInstruction *pci;
1420 int key = mnem2key(mnem);
1422 if(!mnemonics_initialized)
1423 pic14initMnemonics();
1425 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1429 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1430 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1434 pci = hTabNextItemWK (pic14MnemonicsHash);
1441 /*-----------------------------------------------------------------*
1442 * pic14initpCodePeepCommands
1444 *-----------------------------------------------------------------*/
1445 void pic14initpCodePeepCommands(void)
1453 hTabAddItem(&pic14pCodePeepCommandsHash,
1454 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1456 } while (peepCommands[i].cmd);
1458 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1461 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1462 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1467 /*-----------------------------------------------------------------
1470 *-----------------------------------------------------------------*/
1472 int getpCodePeepCommand(char *cmd)
1476 int key = mnem2key(cmd);
1479 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1482 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1483 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1487 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1494 char getpBlock_dbName(pBlock *pb)
1500 return pb->cmemmap->dbName;
1504 void pBlockConvert2ISR(pBlock *pb)
1515 /*-----------------------------------------------------------------*/
1516 /* movepBlock2Head - given the dbname of a pBlock, move all */
1517 /* instances to the front of the doubly linked */
1518 /* list of pBlocks */
1519 /*-----------------------------------------------------------------*/
1521 void movepBlock2Head(char dbName)
1525 pb = the_pFile->pbHead;
1529 if(getpBlock_dbName(pb) == dbName) {
1530 pBlock *pbn = pb->next;
1531 pb->next = the_pFile->pbHead;
1532 the_pFile->pbHead->prev = pb;
1533 the_pFile->pbHead = pb;
1536 pb->prev->next = pbn;
1538 // If the pBlock that we just moved was the last
1539 // one in the link of all of the pBlocks, then we
1540 // need to point the tail to the block just before
1541 // the one we moved.
1542 // Note: if pb->next is NULL, then pb must have
1543 // been the last pBlock in the chain.
1546 pbn->prev = pb->prev;
1548 the_pFile->pbTail = pb->prev;
1559 void copypCode(FILE *of, char dbName)
1563 if(!of || !the_pFile)
1566 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1567 if(getpBlock_dbName(pb) == dbName) {
1574 void pcode_test(void)
1577 DFPRINTF((stderr,"pcode is alive!\n"));
1587 /* create the file name */
1588 strcpy(buffer,dstFileName);
1589 strcat(buffer,".p");
1591 if( !(pFile = fopen(buffer, "w" ))) {
1592 werror(E_FILE_OPEN_ERR,buffer);
1596 fprintf(pFile,"pcode dump\n\n");
1598 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1599 fprintf(pFile,"\n\tNew pBlock\n\n");
1601 fprintf(pFile,"%s",pb->cmemmap->sname);
1603 fprintf(pFile,"internal pblock");
1605 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1606 printpBlock(pFile,pb);
1610 /*-----------------------------------------------------------------*/
1611 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1612 /* ister, RegCond will return the bit being referenced. */
1614 /* fixme - why not just OR in the pcop bit field */
1615 /*-----------------------------------------------------------------*/
1617 static int RegCond(pCodeOp *pcop)
1623 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1624 switch(PCORB(pcop)->bit) {
1638 /*-----------------------------------------------------------------*/
1639 /* newpCode - create and return a newly initialized pCode */
1641 /* fixme - rename this */
1643 /* The purpose of this routine is to create a new Instruction */
1644 /* pCode. This is called by gen.c while the assembly code is being */
1648 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1649 /* (note that the op is analogous to but not the */
1650 /* same thing as the opcode of the instruction.) */
1651 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1654 /* a pointer to the new malloc'd pCode is returned. */
1658 /*-----------------------------------------------------------------*/
1659 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1661 pCodeInstruction *pci ;
1663 if(!mnemonics_initialized)
1664 pic14initMnemonics();
1666 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1668 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1669 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1672 if(pci->inCond & PCC_EXAMINE_PCOP)
1673 pci->inCond |= RegCond(pcop);
1675 if(pci->outCond & PCC_EXAMINE_PCOP)
1676 pci->outCond |= RegCond(pcop);
1678 pci->pc.prev = pci->pc.next = NULL;
1679 return (pCode *)pci;
1682 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1688 /*-----------------------------------------------------------------*/
1689 /* newpCodeWild - create a "wild" as in wild card pCode */
1691 /* Wild pcodes are used during the peep hole optimizer to serve */
1692 /* as place holders for any instruction. When a snippet of code is */
1693 /* compared to a peep hole rule, the wild card opcode will match */
1694 /* any instruction. However, the optional operand and label are */
1695 /* additional qualifiers that must also be matched before the */
1696 /* line (of assembly code) is declared matched. Note that the */
1697 /* operand may be wild too. */
1699 /* Note, a wild instruction is specified just like a wild var: */
1700 /* %4 ; A wild instruction, */
1701 /* See the peeph.def file for additional examples */
1703 /*-----------------------------------------------------------------*/
1705 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1710 pcw = Safe_calloc(1,sizeof(pCodeWild));
1712 pcw->pci.pc.type = PC_WILD;
1713 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1714 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1715 pcw->pci.pc.pb = NULL;
1717 // pcw->pci.pc.analyze = genericAnalyze;
1718 pcw->pci.pc.destruct = genericDestruct;
1719 pcw->pci.pc.print = genericPrint;
1721 pcw->id = pCodeID; // this is the 'n' in %n
1722 pcw->operand = optional_operand;
1723 pcw->label = optional_label;
1725 pcw->mustBeBitSkipInst = 0;
1726 pcw->mustNotBeBitSkipInst = 0;
1727 pcw->invertBitSkipInst = 0;
1729 return ( (pCode *)pcw);
1733 /*-----------------------------------------------------------------*/
1734 /* newPcodeInlineP - create a new pCode from a char string */
1735 /*-----------------------------------------------------------------*/
1738 pCode *newpCodeInlineP(char *cP)
1743 pcc = Safe_calloc(1,sizeof(pCodeComment));
1745 pcc->pc.type = PC_INLINE;
1746 pcc->pc.prev = pcc->pc.next = NULL;
1747 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1750 // pcc->pc.analyze = genericAnalyze;
1751 pcc->pc.destruct = genericDestruct;
1752 pcc->pc.print = genericPrint;
1755 pcc->comment = Safe_strdup(cP);
1757 pcc->comment = NULL;
1759 return ( (pCode *)pcc);
1763 /*-----------------------------------------------------------------*/
1764 /* newPcodeCharP - create a new pCode from a char string */
1765 /*-----------------------------------------------------------------*/
1767 pCode *newpCodeCharP(char *cP)
1772 pcc = Safe_calloc(1,sizeof(pCodeComment));
1774 pcc->pc.type = PC_COMMENT;
1775 pcc->pc.prev = pcc->pc.next = NULL;
1776 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1779 // pcc->pc.analyze = genericAnalyze;
1780 pcc->pc.destruct = genericDestruct;
1781 pcc->pc.print = genericPrint;
1784 pcc->comment = Safe_strdup(cP);
1786 pcc->comment = NULL;
1788 return ( (pCode *)pcc);
1792 /*-----------------------------------------------------------------*/
1793 /* newpCodeFunction - */
1794 /*-----------------------------------------------------------------*/
1797 pCode *newpCodeFunction(char *mod,char *f)
1801 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1802 //_ALLOC(pcf,sizeof(pCodeFunction));
1804 pcf->pc.type = PC_FUNCTION;
1805 pcf->pc.prev = pcf->pc.next = NULL;
1806 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1809 // pcf->pc.analyze = genericAnalyze;
1810 pcf->pc.destruct = genericDestruct;
1811 pcf->pc.print = pCodePrintFunction;
1816 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1817 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1818 strcpy(pcf->modname,mod);
1820 pcf->modname = NULL;
1823 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1824 pcf->fname = Safe_calloc(1,strlen(f)+1);
1825 strcpy(pcf->fname,f);
1829 return ( (pCode *)pcf);
1833 /*-----------------------------------------------------------------*/
1835 /*-----------------------------------------------------------------*/
1836 void destructpCodeFlow(pCode *pc)
1838 if(!pc || !isPCFL(pc))
1847 deleteSet(&PCFL(pc)->registers);
1848 deleteSet(&PCFL(pc)->from);
1849 deleteSet(&PCFL(pc)->to);
1854 pCode *newpCodeFlow(void )
1858 //_ALLOC(pcflow,sizeof(pCodeFlow));
1859 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1861 pcflow->pc.type = PC_FLOW;
1862 pcflow->pc.prev = pcflow->pc.next = NULL;
1863 pcflow->pc.pb = NULL;
1865 // pcflow->pc.analyze = genericAnalyze;
1866 pcflow->pc.destruct = destructpCodeFlow;
1867 pcflow->pc.print = genericPrint;
1869 pcflow->pc.seq = GpcFlowSeq++;
1871 pcflow->from = pcflow->to = NULL;
1873 pcflow->inCond = PCC_NONE;
1874 pcflow->outCond = PCC_NONE;
1876 pcflow->firstBank = -1;
1877 pcflow->lastBank = -1;
1879 pcflow->FromConflicts = 0;
1880 pcflow->ToConflicts = 0;
1884 pcflow->registers = newSet();
1886 return ( (pCode *)pcflow);
1890 /*-----------------------------------------------------------------*/
1891 /*-----------------------------------------------------------------*/
1892 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1894 pCodeFlowLink *pcflowLink;
1896 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1898 pcflowLink->pcflow = pcflow;
1899 pcflowLink->bank_conflict = 0;
1904 /*-----------------------------------------------------------------*/
1905 /* newpCodeCSource - create a new pCode Source Symbol */
1906 /*-----------------------------------------------------------------*/
1908 pCode *newpCodeCSource(int ln, char *f, char *l)
1913 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1915 pccs->pc.type = PC_CSOURCE;
1916 pccs->pc.prev = pccs->pc.next = NULL;
1919 pccs->pc.destruct = genericDestruct;
1920 pccs->pc.print = genericPrint;
1922 pccs->line_number = ln;
1924 pccs->line = Safe_strdup(l);
1929 pccs->file_name = Safe_strdup(f);
1931 pccs->file_name = NULL;
1933 return ( (pCode *)pccs);
1936 /*-----------------------------------------------------------------*/
1937 /* pCodeLabelDestruct - free memory used by a label. */
1938 /*-----------------------------------------------------------------*/
1939 static void pCodeLabelDestruct(pCode *pc)
1945 if((pc->type == PC_LABEL) && PCL(pc)->label)
1946 free(PCL(pc)->label);
1952 pCode *newpCodeLabel(char *name, int key)
1958 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1960 pcl->pc.type = PC_LABEL;
1961 pcl->pc.prev = pcl->pc.next = NULL;
1962 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1965 // pcl->pc.analyze = genericAnalyze;
1966 pcl->pc.destruct = pCodeLabelDestruct;
1967 pcl->pc.print = pCodePrintLabel;
1973 sprintf(s,"_%05d_DS_",key);
1978 pcl->label = Safe_strdup(s);
1980 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1981 return ( (pCode *)pcl);
1986 /*-----------------------------------------------------------------*/
1987 /* newpBlock - create and return a pointer to a new pBlock */
1988 /*-----------------------------------------------------------------*/
1989 pBlock *newpBlock(void)
1994 PpB = Safe_calloc(1,sizeof(pBlock) );
1995 PpB->next = PpB->prev = NULL;
1997 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1998 PpB->tregisters = NULL;
2000 PpB->FlowTree = NULL;
2006 /*-----------------------------------------------------------------*/
2007 /* newpCodeChain - create a new chain of pCodes */
2008 /*-----------------------------------------------------------------*
2010 * This function will create a new pBlock and the pointer to the
2011 * pCode that is passed in will be the first pCode in the block.
2012 *-----------------------------------------------------------------*/
2015 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2018 pBlock *pB = newpBlock();
2020 pB->pcHead = pB->pcTail = pc;
2027 /*-----------------------------------------------------------------*/
2028 /* newpCodeOpLabel - Create a new label given the key */
2029 /* Note, a negative key means that the label is part of wild card */
2030 /* (and hence a wild card label) used in the pCodePeep */
2031 /* optimizations). */
2032 /*-----------------------------------------------------------------*/
2034 pCodeOp *newpCodeOpLabel(char *name, int key)
2037 static int label_key=-1;
2041 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2042 pcop->type = PO_LABEL;
2047 sprintf(s=buffer,"_%05d_DS_",key);
2049 s = name, key = label_key--;
2052 pcop->name = Safe_strdup(s);
2054 ((pCodeOpLabel *)pcop)->key = key;
2056 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2060 /*-----------------------------------------------------------------*/
2061 /*-----------------------------------------------------------------*/
2062 pCodeOp *newpCodeOpLit(int lit)
2068 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2069 pcop->type = PO_LITERAL;
2073 sprintf(s,"0x%02x",lit);
2075 pcop->name = Safe_strdup(s);
2078 ((pCodeOpLit *)pcop)->lit = lit;
2083 /*-----------------------------------------------------------------*/
2084 /*-----------------------------------------------------------------*/
2085 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2089 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2090 pcop->type = PO_IMMEDIATE;
2093 pcop->name = Safe_strdup(name);
2096 r = dirregWithName(name);
2100 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2101 PCOI(pcop)->rIdx = r->rIdx;
2103 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2104 PCOI(pcop)->rIdx = -1;
2106 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2111 PCOI(pcop)->index = index;
2112 PCOI(pcop)->offset = offset;
2113 PCOI(pcop)->_const = code_space;
2114 PCOI(pcop)->_function = is_func;
2119 /*-----------------------------------------------------------------*/
2120 /*-----------------------------------------------------------------*/
2121 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2127 if(!pcwb || !subtype) {
2128 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2132 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2133 pcop->type = PO_WILD;
2134 sprintf(s,"%%%d",id);
2135 pcop->name = Safe_strdup(s);
2137 PCOW(pcop)->id = id;
2138 PCOW(pcop)->pcwb = pcwb;
2139 PCOW(pcop)->subtype = subtype;
2140 PCOW(pcop)->matched = NULL;
2145 /*-----------------------------------------------------------------*/
2146 /*-----------------------------------------------------------------*/
2147 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2151 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2152 pcop->type = PO_GPR_BIT;
2154 pcop->name = Safe_strdup(s);
2158 PCORB(pcop)->bit = bit;
2159 PCORB(pcop)->inBitSpace = inBitSpace;
2161 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2162 PCOR(pcop)->r = NULL;
2163 PCOR(pcop)->rIdx = 0;
2167 /*-----------------------------------------------------------------*
2168 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2170 * If rIdx >=0 then a specific register from the set of registers
2171 * will be selected. If rIdx <0, then a new register will be searched
2173 *-----------------------------------------------------------------*/
2175 pCodeOp *newpCodeOpReg(int rIdx)
2179 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2184 PCOR(pcop)->rIdx = rIdx;
2185 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2187 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2190 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2193 pcop->type = PCOR(pcop)->r->pc_type;
2198 pCodeOp *newpCodeOpRegFromStr(char *name)
2202 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2203 PCOR(pcop)->r = allocRegByName(name, 1);
2204 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2205 pcop->type = PCOR(pcop)->r->pc_type;
2206 pcop->name = PCOR(pcop)->r->name;
2211 /*-----------------------------------------------------------------*/
2212 /*-----------------------------------------------------------------*/
2214 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2221 pcop = newpCodeOpBit(name, -1,0);
2225 pcop = newpCodeOpLit(-1);
2229 pcop = newpCodeOpLabel(NULL,-1);
2232 pcop = newpCodeOpReg(-1);
2235 case PO_GPR_POINTER:
2236 case PO_GPR_REGISTER:
2238 pcop = newpCodeOpRegFromStr(name);
2240 pcop = newpCodeOpReg(-1);
2244 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2247 pcop->name = Safe_strdup(name);
2255 /*-----------------------------------------------------------------*/
2256 /*-----------------------------------------------------------------*/
2257 void pCodeConstString(char *name, char *value)
2261 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2266 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2270 sprintf(buffer,"; %s = %s",name,value);
2272 addpCode2pBlock(pb,newpCodeCharP(buffer));
2273 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2276 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2282 /*-----------------------------------------------------------------*/
2283 /*-----------------------------------------------------------------*/
2284 void pCodeReadCodeTable(void)
2288 fprintf(stderr, " %s\n",__FUNCTION__);
2290 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2294 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2295 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2296 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2297 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2299 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2300 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2301 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2302 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2307 /*-----------------------------------------------------------------*/
2308 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2309 /*-----------------------------------------------------------------*/
2310 void addpCode2pBlock(pBlock *pb, pCode *pc)
2317 /* If this is the first pcode to be added to a block that
2318 * was initialized with a NULL pcode, then go ahead and
2319 * make this pcode the head and tail */
2320 pb->pcHead = pb->pcTail = pc;
2323 pb->pcTail->next = pc;
2325 pc->prev = pb->pcTail;
2332 /*-----------------------------------------------------------------*/
2333 /* addpBlock - place a pBlock into the pFile */
2334 /*-----------------------------------------------------------------*/
2335 void addpBlock(pBlock *pb)
2337 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2340 /* First time called, we'll pass through here. */
2341 //_ALLOC(the_pFile,sizeof(pFile));
2342 the_pFile = Safe_calloc(1,sizeof(pFile));
2343 the_pFile->pbHead = the_pFile->pbTail = pb;
2344 the_pFile->functions = NULL;
2348 the_pFile->pbTail->next = pb;
2349 pb->prev = the_pFile->pbTail;
2351 the_pFile->pbTail = pb;
2354 /*-----------------------------------------------------------------*/
2355 /* removepBlock - remove a pBlock from the pFile */
2356 /*-----------------------------------------------------------------*/
2357 void removepBlock(pBlock *pb)
2365 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2367 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2370 if(pbs == the_pFile->pbHead)
2371 the_pFile->pbHead = pbs->next;
2373 if (pbs == the_pFile->pbTail)
2374 the_pFile->pbTail = pbs->prev;
2377 pbs->next->prev = pbs->prev;
2380 pbs->prev->next = pbs->next;
2387 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2391 /*-----------------------------------------------------------------*/
2392 /* printpCode - write the contents of a pCode to a file */
2393 /*-----------------------------------------------------------------*/
2394 void printpCode(FILE *of, pCode *pc)
2405 fprintf(of,"warning - unable to print pCode\n");
2408 /*-----------------------------------------------------------------*/
2409 /* printpBlock - write the contents of a pBlock to a file */
2410 /*-----------------------------------------------------------------*/
2411 void printpBlock(FILE *of, pBlock *pb)
2421 for(pc = pb->pcHead; pc; pc = pc->next)
2426 /*-----------------------------------------------------------------*/
2428 /* pCode processing */
2432 /*-----------------------------------------------------------------*/
2434 void unlinkpCode(pCode *pc)
2440 fprintf(stderr,"Unlinking: ");
2441 printpCode(stderr, pc);
2444 pc->prev->next = pc->next;
2446 pc->next->prev = pc->prev;
2448 pc->prev = pc->next = NULL;
2452 /*-----------------------------------------------------------------*/
2453 /*-----------------------------------------------------------------*/
2455 static void genericDestruct(pCode *pc)
2461 /* For instructions, tell the register (if there's one used)
2462 * that it's no longer needed */
2463 regs *reg = getRegFromInstruction(pc);
2465 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2468 /* Instead of deleting the memory used by this pCode, mark
2469 * the object as bad so that if there's a pointer to this pCode
2470 * dangling around somewhere then (hopefully) when the type is
2471 * checked we'll catch it.
2476 addpCode2pBlock(pb_dead_pcodes, pc);
2483 /*-----------------------------------------------------------------*/
2484 /*-----------------------------------------------------------------*/
2485 void pBlockRegs(FILE *of, pBlock *pb)
2490 r = setFirstItem(pb->tregisters);
2492 r = setNextItem(pb->tregisters);
2497 /*-----------------------------------------------------------------*/
2498 /*-----------------------------------------------------------------*/
2499 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2504 int use_buffer = 1; // copy the string to the passed buffer pointer
2509 use_buffer = 0; // Don't bother copying the string to the buffer.
2513 switch(pcop->type) {
2517 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2520 //return PCOR(pcop)->r->name;
2524 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2527 SAFE_snprintf(&buffer,&size,"%s",r->name);
2537 if(PCOI(pcop)->_const) {
2539 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2540 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2543 8 * PCOI(pcop)->offset );
2545 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2548 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2549 SAFE_snprintf(&s,&size,"(%s + %d)",
2551 PCOI(pcop)->index );
2553 if(PCOI(pcop)->offset)
2554 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2556 SAFE_snprintf(&s,&size,"%s",pcop->name);
2564 //size = sizeof(buffer);
2565 if( PCOR(pcop)->instance) {
2566 SAFE_snprintf(&s,&size,"(%s + %d)",
2568 PCOR(pcop)->instance );
2569 //fprintf(stderr,"PO_DIR %s\n",buffer);
2571 SAFE_snprintf(&s,&size,"%s",pcop->name);
2577 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2586 return "NO operand";
2590 /*-----------------------------------------------------------------*/
2591 /*-----------------------------------------------------------------*/
2592 static char *get_op_from_instruction( pCodeInstruction *pcc)
2596 return get_op(pcc->pcop,NULL,0);
2598 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2599 return ("ERROR Null: "__FUNCTION__);
2601 return ("ERROR Null: get_op_from_instruction");
2605 /*-----------------------------------------------------------------*/
2606 /*-----------------------------------------------------------------*/
2607 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2610 fprintf(of,"pcodeopprint- not implemented\n");
2613 /*-----------------------------------------------------------------*/
2614 /*-----------------------------------------------------------------*/
2615 char *pCode2str(char *str, size_t size, pCode *pc)
2623 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2625 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2627 if(PCI(pc)->isBitInst) {
2628 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2629 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2630 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2631 PCI(pc)->pcop->name ,
2632 PCI(pc)->pcop->name );
2634 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2635 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2636 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2637 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2639 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2640 //PCI(pc)->pcop->t.bit );
2643 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2644 if( PCI(pc)->num_ops == 2)
2645 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2647 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2650 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2652 if( PCI(pc)->num_ops == 2)
2653 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2661 /* assuming that comment ends with a \n */
2662 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2666 /* assuming that inline code ends with a \n */
2667 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2671 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2674 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2677 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2680 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2683 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2687 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2694 /*-----------------------------------------------------------------*/
2695 /* genericPrint - the contents of a pCode to a file */
2696 /*-----------------------------------------------------------------*/
2697 static void genericPrint(FILE *of, pCode *pc)
2705 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2709 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2713 // If the opcode has a label, print that first
2715 pBranch *pbl = PCI(pc)->label;
2716 while(pbl && pbl->pc) {
2717 if(pbl->pc->type == PC_LABEL)
2718 pCodePrintLabel(of, pbl->pc);
2724 genericPrint(of,PCODE(PCI(pc)->cline));
2729 pCode2str(str, 256, pc);
2731 fprintf(of,"%s",str);
2735 fprintf(of, "\t;key=%03x",pc->seq);
2737 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2742 pBranch *dpb = pc->to; // debug
2744 switch ( dpb->pc->type) {
2746 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2749 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2752 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2755 fprintf(of, "\t;flow");
2769 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2770 if(PCW(pc)->pci.label)
2771 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2773 if(PCW(pc)->operand) {
2774 fprintf(of,";\toperand ");
2775 pCodeOpPrint(of,PCW(pc)->operand );
2781 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2782 if(PCFL(pc)->ancestor)
2783 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2790 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2794 fprintf(of,"unknown pCode type %d\n",pc->type);
2799 /*-----------------------------------------------------------------*/
2800 /* pCodePrintFunction - prints function begin/end */
2801 /*-----------------------------------------------------------------*/
2803 static void pCodePrintFunction(FILE *of, pCode *pc)
2809 if( ((pCodeFunction *)pc)->modname)
2810 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2812 if(PCF(pc)->fname) {
2813 pBranch *exits = PCF(pc)->to;
2815 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2818 exits = exits->next;
2821 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2824 if((PCF(pc)->from &&
2825 PCF(pc)->from->pc->type == PC_FUNCTION &&
2826 PCF(PCF(pc)->from->pc)->fname) )
2827 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2829 fprintf(of,"; exit point [can't find entry point]\n");
2832 /*-----------------------------------------------------------------*/
2833 /* pCodePrintLabel - prints label */
2834 /*-----------------------------------------------------------------*/
2836 static void pCodePrintLabel(FILE *of, pCode *pc)
2843 fprintf(of,"%s\n",PCL(pc)->label);
2844 else if (PCL(pc)->key >=0)
2845 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2847 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2850 /*-----------------------------------------------------------------*/
2851 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2852 /* remove it if it is found. */
2853 /*-----------------------------------------------------------------*/
2854 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2861 if(pcl->type == PC_OPCODE)
2862 b = PCI(pcl)->label;
2864 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2869 //fprintf (stderr, "%s \n",__FUNCTION__);
2870 //pcl->print(stderr,pcl);
2871 //pc->print(stderr,pc);
2874 //fprintf (stderr, "found label\n");
2878 bprev->next = b->next; /* Not first pCode in chain */
2882 PCI(pcl)->label = b->next; /* First pCode in chain */
2885 return; /* A label can't occur more than once */
2893 /*-----------------------------------------------------------------*/
2894 /*-----------------------------------------------------------------*/
2895 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2914 /*-----------------------------------------------------------------*/
2915 /* pBranchLink - given two pcodes, this function will link them */
2916 /* together through their pBranches */
2917 /*-----------------------------------------------------------------*/
2918 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2922 // Declare a new branch object for the 'from' pCode.
2924 //_ALLOC(b,sizeof(pBranch));
2925 b = Safe_calloc(1,sizeof(pBranch));
2926 b->pc = PCODE(t); // The link to the 'to' pCode.
2929 f->to = pBranchAppend(f->to,b);
2931 // Now do the same for the 'to' pCode.
2933 //_ALLOC(b,sizeof(pBranch));
2934 b = Safe_calloc(1,sizeof(pBranch));
2938 t->from = pBranchAppend(t->from,b);
2943 /*-----------------------------------------------------------------*/
2944 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2946 /*-----------------------------------------------------------------*/
2947 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2960 /*-----------------------------------------------------------------*/
2961 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2962 /*-----------------------------------------------------------------*/
2963 static void pCodeUnlink(pCode *pc)
2968 if(!pc->prev || !pc->next) {
2969 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2973 /* first remove the pCode from the chain */
2974 pc->prev->next = pc->next;
2975 pc->next->prev = pc->prev;
2977 /* Now for the hard part... */
2979 /* Remove the branches */
2983 pc1 = pb1->pc; /* Get the pCode that branches to the
2984 * one we're unlinking */
2986 /* search for the link back to this pCode (the one we're
2988 if(pb2 = pBranchFind(pc1->to,pc)) {
2989 pb2->pc = pc->to->pc; // make the replacement
2991 /* if the pCode we're unlinking contains multiple 'to'
2992 * branches (e.g. this a skip instruction) then we need
2993 * to copy these extra branches to the chain. */
2995 pBranchAppend(pb2, pc->to->next);
3004 /*-----------------------------------------------------------------*/
3005 /*-----------------------------------------------------------------*/
3007 static void genericAnalyze(pCode *pc)
3017 // Go through the pCodes that are in pCode chain and link
3018 // them together through the pBranches. Note, the pCodes
3019 // are linked together as a contiguous stream like the
3020 // assembly source code lines. The linking here mimics this
3021 // except that comments are not linked in.
3023 pCode *npc = pc->next;
3025 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3026 pBranchLink(pc,npc);
3031 /* reached the end of the pcode chain without finding
3032 * an instruction we could link to. */
3036 fprintf(stderr,"analyze PC_FLOW\n");
3040 fprintf(stderr,,";A bad pCode is being used\n");
3046 /*-----------------------------------------------------------------*/
3047 /*-----------------------------------------------------------------*/
3048 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3052 if(pc->type == PC_LABEL) {
3053 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3056 if(pc->type == PC_OPCODE) {
3057 pbr = PCI(pc)->label;
3059 if(pbr->pc->type == PC_LABEL) {
3060 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3070 /*-----------------------------------------------------------------*/
3071 /*-----------------------------------------------------------------*/
3072 int checkLabel(pCode *pc)
3076 if(pc && isPCI(pc)) {
3077 pbr = PCI(pc)->label;
3079 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3089 /*-----------------------------------------------------------------*/
3090 /* findLabelinpBlock - Search the pCode for a particular label */
3091 /*-----------------------------------------------------------------*/
3092 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3099 for(pc = pb->pcHead; pc; pc = pc->next)
3100 if(compareLabel(pc,pcop_label))
3106 /*-----------------------------------------------------------------*/
3107 /* findLabel - Search the pCode for a particular label */
3108 /*-----------------------------------------------------------------*/
3109 pCode * findLabel(pCodeOpLabel *pcop_label)
3117 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3118 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3122 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3126 /*-----------------------------------------------------------------*/
3127 /* findNextpCode - given a pCode, find the next of type 'pct' */
3128 /* in the linked list */
3129 /*-----------------------------------------------------------------*/
3130 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3143 /*-----------------------------------------------------------------*/
3144 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3145 /* in the linked list */
3146 /*-----------------------------------------------------------------*/
3147 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3159 /*-----------------------------------------------------------------*/
3160 /* findNextInstruction - given a pCode, find the next instruction */
3161 /* in the linked list */
3162 /*-----------------------------------------------------------------*/
3163 pCode * findNextInstruction(pCode *pci)
3168 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3172 fprintf(stderr,"findNextInstruction: ");
3173 printpCode(stderr, pc);
3178 //fprintf(stderr,"Couldn't find instruction\n");
3182 /*-----------------------------------------------------------------*/
3183 /* findNextInstruction - given a pCode, find the next instruction */
3184 /* in the linked list */
3185 /*-----------------------------------------------------------------*/
3186 pCode * findPrevInstruction(pCode *pci)
3188 return findPrevpCode(pci, PC_OPCODE);
3191 /*-----------------------------------------------------------------*/
3192 /* findFunctionEnd - given a pCode find the end of the function */
3193 /* that contains it */
3194 /*-----------------------------------------------------------------*/
3195 pCode * findFunctionEnd(pCode *pc)
3199 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3205 fprintf(stderr,"Couldn't find function end\n");
3210 /*-----------------------------------------------------------------*/
3211 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3212 /* instruction with which it is associated. */
3213 /*-----------------------------------------------------------------*/
3214 static void AnalyzeLabel(pCode *pc)
3223 static void AnalyzeGOTO(pCode *pc)
3226 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3230 static void AnalyzeSKIP(pCode *pc)
3233 pBranchLink(pc,findNextInstruction(pc->next));
3234 pBranchLink(pc,findNextInstruction(pc->next->next));
3238 static void AnalyzeRETURN(pCode *pc)
3241 // branch_link(pc,findFunctionEnd(pc->next));
3247 /*-----------------------------------------------------------------*/
3248 /*-----------------------------------------------------------------*/
3249 regs * getRegFromInstruction(pCode *pc)
3255 PCI(pc)->num_ops == 0 )
3258 switch(PCI(pc)->pcop->type) {
3261 return PCOR(PCI(pc)->pcop)->r;
3263 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3267 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3268 return PCOR(PCI(pc)->pcop)->r;
3271 if(PCOI(PCI(pc)->pcop)->r)
3272 return (PCOI(PCI(pc)->pcop)->r);
3274 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3275 return dirregWithName(PCI(pc)->pcop->name);
3276 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3279 return PCOR(PCI(pc)->pcop)->r;
3282 //fprintf(stderr, "getRegFromInstruction - dir\n");
3283 return PCOR(PCI(pc)->pcop)->r;
3285 //fprintf(stderr, "getRegFromInstruction - literal\n");
3289 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3290 //genericPrint(stderr, pc);
3298 /*-----------------------------------------------------------------*/
3299 /*-----------------------------------------------------------------*/
3301 void AnalyzepBlock(pBlock *pb)
3308 /* Find all of the registers used in this pBlock
3309 * by looking at each instruction and examining it's
3312 for(pc = pb->pcHead; pc; pc = pc->next) {
3314 /* Is this an instruction with operands? */
3315 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3317 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3319 /* Loop through all of the registers declared so far in
3320 this block and see if we find this one there */
3322 regs *r = setFirstItem(pb->tregisters);
3325 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3326 PCOR(PCI(pc)->pcop)->r = r;
3329 r = setNextItem(pb->tregisters);
3333 /* register wasn't found */
3334 //r = Safe_calloc(1, sizeof(regs));
3335 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3336 //addSet(&pb->tregisters, r);
3337 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3338 //PCOR(PCI(pc)->pcop)->r = r;
3339 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3341 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3344 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3345 if(PCOR(PCI(pc)->pcop)->r) {
3346 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3347 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3349 if(PCI(pc)->pcop->name)
3350 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3352 fprintf(stderr,"ERROR: NULL register\n");
3361 /*-----------------------------------------------------------------*/
3363 /*-----------------------------------------------------------------*/
3364 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3366 void InsertpFlow(pCode *pc, pCode **pflow)
3369 PCFL(*pflow)->end = pc;
3371 if(!pc || !pc->next)
3374 *pflow = newpCodeFlow();
3375 pCodeInsertAfter(pc, *pflow);
3378 /*-----------------------------------------------------------------*/
3379 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3380 /* the flow blocks. */
3382 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3383 * point the instruction flow changes.
3385 /*-----------------------------------------------------------------*/
3386 void BuildFlow(pBlock *pb)
3389 pCode *last_pci=NULL;
3396 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3397 /* Insert a pCodeFlow object at the beginning of a pBlock */
3399 InsertpFlow(pb->pcHead, &pflow);
3401 //pflow = newpCodeFlow(); /* Create a new Flow object */
3402 //pflow->next = pb->pcHead; /* Make the current head the next object */
3403 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3404 //pb->pcHead = pflow; /* Make the Flow object the head */
3407 for( pc = findNextInstruction(pb->pcHead);
3409 pc=findNextInstruction(pc)) {
3412 PCI(pc)->pcflow = PCFL(pflow);
3414 //fprintf(stderr," build: ");
3415 //pflow->print(stderr,pflow);
3417 if( PCI(pc)->isSkip) {
3419 /* The two instructions immediately following this one
3420 * mark the beginning of a new flow segment */
3422 while(pc && PCI(pc)->isSkip) {
3424 PCI(pc)->pcflow = PCFL(pflow);
3428 InsertpFlow(pc, &pflow);
3429 pc=findNextInstruction(pc->next);
3437 PCI(pc)->pcflow = PCFL(pflow);
3439 InsertpFlow(pc, &pflow);
3441 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3443 InsertpFlow(pc, &pflow);
3446 } else if (checkLabel(pc)) {
3448 /* This instruction marks the beginning of a
3449 * new flow segment */
3454 /* If the previous pCode is not a flow object, then
3455 * insert a new flow object. (This check prevents
3456 * two consecutive flow objects from being insert in
3457 * the case where a skip instruction preceeds an
3458 * instruction containing a label.) */
3460 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3461 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3463 PCI(pc)->pcflow = PCFL(pflow);
3470 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3472 PCFL(pflow)->end = pb->pcTail;
3475 /*-------------------------------------------------------------------*/
3476 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3477 /* the flow blocks. */
3479 * unBuildFlow removes pCodeFlow objects from a pCode chain
3481 /*-----------------------------------------------------------------*/
3482 void unBuildFlow(pBlock *pb)
3497 if(PCI(pc)->pcflow) {
3498 //free(PCI(pc)->pcflow);
3499 PCI(pc)->pcflow = NULL;
3502 } else if(isPCFL(pc) )
3511 /*-----------------------------------------------------------------*/
3512 /*-----------------------------------------------------------------*/
3513 void dumpCond(int cond)
3516 static char *pcc_str[] = {
3530 int ncond = sizeof(pcc_str) / sizeof(char *);
3533 fprintf(stderr, "0x%04X\n",cond);
3535 for(i=0,j=1; i<ncond; i++, j<<=1)
3537 fprintf(stderr, " %s\n",pcc_str[i]);
3541 /*-----------------------------------------------------------------*/
3542 /*-----------------------------------------------------------------*/
3543 void FlowStats(pCodeFlow *pcflow)
3551 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3553 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3556 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3561 fprintf(stderr, " FlowStats inCond: ");
3562 dumpCond(pcflow->inCond);
3563 fprintf(stderr, " FlowStats outCond: ");
3564 dumpCond(pcflow->outCond);
3568 /*-----------------------------------------------------------------*
3569 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3570 * if it affects the banking bits.
3572 * return: -1 == Banking bits are unaffected by this pCode.
3574 * return: > 0 == Banking bits are affected.
3576 * If the banking bits are affected, then the returned value describes
3577 * which bits are affected and how they're affected. The lower half
3578 * of the integer maps to the bits that are affected, the upper half
3579 * to whether they're set or cleared.
3581 *-----------------------------------------------------------------*/
3582 #define SET_BANK_BIT (1 << 16)
3583 #define CLR_BANK_BIT 0
3585 int isBankInstruction(pCode *pc)
3593 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3595 /* Check to see if the register banks are changing */
3596 if(PCI(pc)->isModReg) {
3598 pCodeOp *pcop = PCI(pc)->pcop;
3599 switch(PCI(pc)->op) {
3602 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3603 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3604 return SET_BANK_BIT | PIC_RP0_BIT;
3607 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3608 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3609 return CLR_BANK_BIT | PIC_RP0_BIT;
3614 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3615 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3616 return CLR_BANK_BIT | PIC_RP1_BIT;
3618 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3619 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3620 return CLR_BANK_BIT | PIC_RP1_BIT;
3624 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3625 //genericPrint(stderr, pc);
3636 /*-----------------------------------------------------------------*/
3637 /*-----------------------------------------------------------------*/
3638 void FillFlow(pCodeFlow *pcflow)
3647 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3649 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3652 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3659 isBankInstruction(pc);
3661 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3665 fprintf(stderr, " FillFlow - Bad end of flow\n");
3667 fprintf(stderr, " FillFlow - Ending flow with\n ");
3668 pc->print(stderr,pc);
3671 fprintf(stderr, " FillFlow inCond: ");
3672 dumpCond(pcflow->inCond);
3673 fprintf(stderr, " FillFlow outCond: ");
3674 dumpCond(pcflow->outCond);
3678 /*-----------------------------------------------------------------*/
3679 /*-----------------------------------------------------------------*/
3680 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3682 pCodeFlowLink *fromLink, *toLink;
3684 if(!from || !to || !to->pcflow || !from->pcflow)
3687 fromLink = newpCodeFlowLink(from->pcflow);
3688 toLink = newpCodeFlowLink(to->pcflow);
3690 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3691 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3695 /*-----------------------------------------------------------------*
3696 * void LinkFlow(pBlock *pb)
3698 * In BuildFlow, the PIC code has been partitioned into contiguous
3699 * non-branching segments. In LinkFlow, we determine the execution
3700 * order of these segments. For example, if one of the segments ends
3701 * with a skip, then we know that there are two possible flow segments
3702 * to which control may be passed.
3703 *-----------------------------------------------------------------*/
3704 void LinkFlow(pBlock *pb)
3710 //fprintf(stderr,"linkflow \n");
3712 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3714 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3717 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3719 //fprintf(stderr," link: ");
3720 //pcflow->print(stderr,pcflow);
3722 //FillFlow(PCFL(pcflow));
3724 pc = PCFL(pcflow)->end;
3726 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3727 if(isPCI_SKIP(pc)) {
3728 //fprintf(stderr, "ends with skip\n");
3729 //pc->print(stderr,pc);
3730 pct=findNextInstruction(pc->next);
3731 LinkFlow_pCode(PCI(pc),PCI(pct));
3732 pct=findNextInstruction(pct->next);
3733 LinkFlow_pCode(PCI(pc),PCI(pct));
3737 if(isPCI_BRANCH(pc)) {
3738 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3740 //fprintf(stderr, "ends with branch\n ");
3741 //pc->print(stderr,pc);
3743 if(!(pcol && isPCOLAB(pcol))) {
3744 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3745 pc->print(stderr,pc);
3746 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3751 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3752 LinkFlow_pCode(PCI(pc),PCI(pct));
3754 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3755 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3756 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3762 //fprintf(stderr, "ends with non-branching instruction:\n");
3763 //pc->print(stderr,pc);
3765 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3771 //fprintf(stderr, "ends with unknown\n");
3772 //pc->print(stderr,pc);
3776 //fprintf(stderr, "ends with nothing: ERROR\n");
3780 /*-----------------------------------------------------------------*/
3781 /*-----------------------------------------------------------------*/
3783 /*-----------------------------------------------------------------*/
3784 /*-----------------------------------------------------------------*/
3785 int isPCinFlow(pCode *pc, pCode *pcflow)
3791 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3794 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3800 /*-----------------------------------------------------------------*/
3801 /*-----------------------------------------------------------------*/
3802 void BanksUsedFlow2(pCode *pcflow)
3811 if(!isPCFL(pcflow)) {
3812 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3816 pc = findNextInstruction(pcflow->next);
3818 PCFL(pcflow)->lastBank = -1;
3820 while(isPCinFlow(pc,pcflow)) {
3822 int bank_selected = isBankInstruction(pc);
3824 //if(PCI(pc)->pcflow)
3825 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3827 if(bank_selected > 0) {
3828 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3830 /* This instruction is modifying banking bits before accessing registers */
3832 PCFL(pcflow)->firstBank = -1;
3834 if(PCFL(pcflow)->lastBank == -1)
3835 PCFL(pcflow)->lastBank = 0;
3837 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3838 if(bank_selected & SET_BANK_BIT)
3839 PCFL(pcflow)->lastBank |= bank;
3843 reg = getRegFromInstruction(pc);
3845 if(reg && !isREGinBank(reg, bank)) {
3846 int allbanks = REGallBanks(reg);
3848 PCFL(pcflow)->firstBank = allbanks;
3850 PCFL(pcflow)->lastBank = allbanks;
3857 pc = findNextInstruction(pc->next);
3860 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3861 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3866 /*-----------------------------------------------------------------*/
3867 /*-----------------------------------------------------------------*/
3868 void BanksUsedFlow(pBlock *pb)
3873 //pb->pcHead->print(stderr, pb->pcHead);
3875 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3876 //pcflow->print(stderr,pcflow);
3878 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3880 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3882 BanksUsedFlow2(pcflow);
3888 /*-----------------------------------------------------------------*/
3889 /*-----------------------------------------------------------------*/
3890 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3898 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3900 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3901 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3904 /* insert the bank switch after this pc instruction */
3905 pCode *pcnext = findNextInstruction(pc);
3906 pCodeInsertAfter(pc, new_pc);
3911 pCodeInsertAfter(pc->prev, new_pc);
3913 /* Move the label, if there is one */
3915 if(PCI(pc)->label) {
3916 PCI(new_pc)->label = PCI(pc)->label;
3917 PCI(pc)->label = NULL;
3920 /* The new instruction has the same pcflow block */
3921 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3924 /*-----------------------------------------------------------------*/
3925 /*-----------------------------------------------------------------*/
3926 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3937 pc = findNextInstruction(pcfl->pc.next);
3939 while(isPCinFlow(pc,PCODE(pcfl))) {
3941 reg = getRegFromInstruction(pc);
3944 fprintf(stderr, " %s ",reg->name);
3945 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3950 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
3951 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
3954 /* Examine the instruction before this one to make sure it is
3955 * not a skip type instruction */
3956 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3958 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3962 reg_bank = (reg) ? REG_BANK(reg) : 0;
3964 b = cur_bank ^ reg_bank;
3966 //fprintf(stderr, "Cool! can switch banks\n");
3967 cur_bank = reg_bank;
3972 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3975 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3976 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3980 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3981 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3983 insertBankSwitch(0, pc, -1, -1);
3989 //fprintf(stderr, "Bummer can't switch banks\n");
3995 pc = findNextInstruction(pc->next);
3999 if(pcprev && cur_bank) {
4000 /* Brute force - make sure that we point to bank 0 at the
4001 * end of each flow block */
4002 new_pc = newpCode(POC_BCF,
4003 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4004 pCodeInsertAfter(pcprev, new_pc);
4010 /*-----------------------------------------------------------------*/
4011 /*int compareBankFlow - compare the banking requirements between */
4013 /*-----------------------------------------------------------------*/
4014 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4017 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4020 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4023 if(pcflow->firstBank == -1)
4027 if(pcflowLink->pcflow->firstBank == -1) {
4028 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4029 pcflowLink->pcflow->to :
4030 pcflowLink->pcflow->from);
4031 return compareBankFlow(pcflow, pctl, toORfrom);
4035 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4038 pcflowLink->bank_conflict++;
4039 pcflowLink->pcflow->FromConflicts++;
4040 pcflow->ToConflicts++;
4043 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4046 pcflowLink->bank_conflict++;
4047 pcflowLink->pcflow->ToConflicts++;
4048 pcflow->FromConflicts++;
4052 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4053 pcflowLink->pcflow->pc.seq,
4054 pcflowLink->pcflow->FromConflicts,
4055 pcflowLink->pcflow->ToConflicts);
4060 /*-----------------------------------------------------------------*/
4061 /*-----------------------------------------------------------------*/
4062 void FixBankFlow(pBlock *pb)
4066 pCodeFlowLink *pcfl;
4068 pCode *pcflow_max_To=NULL;
4069 pCode *pcflow_max_From=NULL;
4070 int max_ToConflicts=0;
4071 int max_FromConflicts=0;
4073 //fprintf(stderr,"Fix Bank flow \n");
4074 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4078 First loop through all of the flow objects in this pcode block
4079 and fix the ones that have banking conflicts between the
4083 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4085 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4087 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4089 if(!isPCFL(pcflow)) {
4090 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4094 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4095 PCFL(pcflow)->firstBank >= 0 &&
4096 PCFL(pcflow)->lastBank >= 0 ) {
4098 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4099 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4101 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4102 BanksUsedFlow2(pcflow);
4107 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4109 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4111 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4116 if(!isPCFL(pcflow)) {
4117 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4121 PCFL(pcflow)->FromConflicts = 0;
4122 PCFL(pcflow)->ToConflicts = 0;
4127 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4128 pcfl = setFirstItem(PCFL(pcflow)->from);
4131 pc = PCODE(pcfl->pcflow);
4134 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4135 pc->print(stderr,pc);
4138 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4141 pcfl=setNextItem(PCFL(pcflow)->from);
4144 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4145 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4147 FixRegisterBankingInFlow(PCFL(pcflow),0);
4148 BanksUsedFlow2(pcflow);
4150 continue; /* Don't need to check the flow from here - it's already been fixed */
4157 pcfl = setFirstItem(PCFL(pcflow)->to);
4160 pc = PCODE(pcfl->pcflow);
4162 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4163 pc->print(stderr,pc);
4166 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4169 pcfl=setNextItem(PCFL(pcflow)->to);
4172 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4173 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4175 FixRegisterBankingInFlow(PCFL(pcflow),0);
4176 BanksUsedFlow2(pcflow);
4181 Loop through the flow objects again and find the ones with the
4185 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4187 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4189 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4190 pcflow_max_To = pcflow;
4192 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4193 pcflow_max_From = pcflow;
4197 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4198 PCFL(pcflow_max_To)->pc.seq,
4199 PCFL(pcflow_max_To)->ToConflicts);
4202 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4203 PCFL(pcflow_max_From)->pc.seq,
4204 PCFL(pcflow_max_From)->FromConflicts);
4208 /*-----------------------------------------------------------------*/
4209 /*-----------------------------------------------------------------*/
4210 void DumpFlow(pBlock *pb)
4214 pCodeFlowLink *pcfl;
4217 fprintf(stderr,"Dump flow \n");
4218 pb->pcHead->print(stderr, pb->pcHead);
4220 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4221 pcflow->print(stderr,pcflow);
4223 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4225 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4227 if(!isPCFL(pcflow)) {
4228 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4231 fprintf(stderr,"dumping: ");
4232 pcflow->print(stderr,pcflow);
4233 FlowStats(PCFL(pcflow));
4235 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4237 pc = PCODE(pcfl->pcflow);
4239 fprintf(stderr, " from seq %d:\n",pc->seq);
4241 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4242 pc->print(stderr,pc);
4247 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4249 pc = PCODE(pcfl->pcflow);
4251 fprintf(stderr, " to seq %d:\n",pc->seq);
4253 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4254 pc->print(stderr,pc);
4263 /*-----------------------------------------------------------------*/
4264 /*-----------------------------------------------------------------*/
4265 int OptimizepBlock(pBlock *pb)
4270 if(!pb || !peepOptimizing)
4273 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4275 for(pc = pb->pcHead; pc; pc = pc->next)
4276 matches += pCodePeepMatchRule(pc);
4279 pc = findNextInstruction(pb->pcHead);
4287 if(pCodePeepMatchRule(pc)) {
4292 pc = findNextInstruction(pcprev->next);
4294 pc = findNextInstruction(pb->pcHead);
4296 pc = findNextInstruction(pc->next);
4300 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4305 /*-----------------------------------------------------------------*/
4306 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4307 /*-----------------------------------------------------------------*/
4308 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4312 for(pc = pcs; pc; pc = pc->next) {
4314 if((pc->type == PC_OPCODE) &&
4316 (PCI(pc)->pcop->type == PO_LABEL) &&
4317 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4325 /*-----------------------------------------------------------------*/
4326 /*-----------------------------------------------------------------*/
4327 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4334 (PCI(pc)->pcop->type == PO_LABEL)) {
4336 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4338 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4340 free(pcol->pcop.name);
4342 /* If the key is negative, then we (probably) have a label to
4343 * a function and the name is already defined */
4346 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4350 //sprintf(buffer,"_%05d_DS_",pcl->key);
4352 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4354 pcol->pcop.name = Safe_strdup(s);
4355 pcol->key = pcl->key;
4356 //pc->print(stderr,pc);
4363 /*-----------------------------------------------------------------*/
4364 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4365 /* pCode chain if they're not used. */
4366 /*-----------------------------------------------------------------*/
4367 void pBlockRemoveUnusedLabels(pBlock *pb)
4369 pCode *pc; pCodeLabel *pcl;
4374 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4376 pBranch *pbr = PCI(pc)->label;
4377 if(pbr && pbr->next) {
4378 pCode *pcd = pb->pcHead;
4380 //fprintf(stderr, "multiple labels\n");
4381 //pc->print(stderr,pc);
4386 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4387 //fprintf(stderr,"Used by:\n");
4388 //pcd->print(stderr,pcd);
4390 exchangeLabels(PCL(pbr->pc),pcd);
4399 for(pc = pb->pcHead; pc; pc = pc->next) {
4401 if(isPCL(pc)) // pc->type == PC_LABEL)
4403 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4404 pcl = PCL(PCI(pc)->label->pc);
4407 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4409 /* This pCode is a label, so search the pBlock to see if anyone
4412 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4413 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4414 /* Couldn't find an instruction that refers to this label
4415 * So, unlink the pCode label from it's pCode chain
4416 * and destroy the label */
4417 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4419 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4420 if(pc->type == PC_LABEL) {
4422 pCodeLabelDestruct(pc);
4424 unlinkpCodeFromBranch(pc, PCODE(pcl));
4425 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4436 /*-----------------------------------------------------------------*/
4437 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4438 /* chain and put them into pBranches that are */
4439 /* associated with the appropriate pCode */
4441 /*-----------------------------------------------------------------*/
4442 void pBlockMergeLabels(pBlock *pb)
4445 pCode *pc, *pcnext=NULL;
4450 /* First, Try to remove any unused labels */
4451 //pBlockRemoveUnusedLabels(pb);
4453 /* Now loop through the pBlock and merge the labels with the opcodes */
4456 // for(pc = pb->pcHead; pc; pc = pc->next) {
4459 pCode *pcn = pc->next;
4461 if(pc->type == PC_LABEL) {
4463 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4464 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4465 if((pcnext = findNextInstruction(pc) )) {
4467 // Unlink the pCode label from it's pCode chain
4470 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4471 // And link it into the instruction's pBranch labels. (Note, since
4472 // it's possible to have multiple labels associated with one instruction
4473 // we must provide a means to accomodate the additional labels. Thus
4474 // the labels are placed into the singly-linked list "label" as
4475 // opposed to being a single member of the pCodeInstruction.)
4477 //_ALLOC(pbr,sizeof(pBranch));
4478 pbr = Safe_calloc(1,sizeof(pBranch));
4482 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4485 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4487 } else if(pc->type == PC_CSOURCE) {
4489 /* merge the source line symbolic info into the next instruction */
4490 if((pcnext = findNextInstruction(pc) )) {
4492 // Unlink the pCode label from it's pCode chain
4494 PCI(pcnext)->cline = PCCS(pc);
4495 //fprintf(stderr, "merging CSRC\n");
4496 //genericPrint(stderr,pcnext);
4502 pBlockRemoveUnusedLabels(pb);
4506 /*-----------------------------------------------------------------*/
4507 /*-----------------------------------------------------------------*/
4508 int OptimizepCode(char dbName)
4510 #define MAX_PASSES 4
4519 DFPRINTF((stderr," Optimizing pCode\n"));
4523 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4524 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4525 matches += OptimizepBlock(pb);
4528 while(matches && ++passes < MAX_PASSES);
4533 /*-----------------------------------------------------------------*/
4534 /* popCopyGPR2Bit - copy a pcode operator */
4535 /*-----------------------------------------------------------------*/
4537 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4541 pcop = newpCodeOpBit(pc->name, bitval, 0);
4543 if( !( (pcop->type == PO_LABEL) ||
4544 (pcop->type == PO_LITERAL) ||
4545 (pcop->type == PO_STR) ))
4546 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4554 /*-----------------------------------------------------------------*/
4555 /*-----------------------------------------------------------------*/
4556 int InstructionRegBank(pCode *pc)
4560 if( (reg = getRegFromInstruction(pc)) == NULL)
4563 return REG_BANK(reg);
4568 /*-----------------------------------------------------------------*/
4569 /*-----------------------------------------------------------------*/
4570 void FixRegisterBanking(pBlock *pb)
4581 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4582 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4585 /* loop through all of the flow blocks with in one pblock */
4587 //fprintf(stderr,"Register banking\n");
4590 /* at this point, pc should point to a PC_FLOW object */
4593 /* for each flow block, determine the register banking
4598 //genericPrint(stderr, pc);
4600 reg = getRegFromInstruction(pc);
4603 fprintf(stderr, " %s ",reg->name);
4604 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4605 reg->address,REG_BANK(reg),reg->isBitField);
4610 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4611 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4615 /* Examine the instruction before this one to make sure it is
4616 * not a skip type instruction */
4617 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4619 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4623 reg_bank = (reg) ? REG_BANK(reg) : 0;
4625 b = cur_bank ^ reg_bank;
4627 cur_bank = reg_bank;
4632 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4635 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4636 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4640 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4641 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4643 insertBankSwitch(0, pc, -1, -1);
4649 //fprintf(stderr, "Bummer can't switch banks\n");
4659 // } while(pc && !(isPCFL(pc)));
4664 if(pcprev && cur_bank) {
4666 int pos = 1; /* Assume that the bank swithc instruction(s)
4667 * are inserted after this instruction */
4669 if((PCI(pcprev)->op == POC_RETLW) ||
4670 (PCI(pcprev)->op == POC_RETURN) ||
4671 (PCI(pcprev)->op == POC_RETFIE)) {
4673 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4679 /* Brute force - make sure that we point to bank 0 at the
4680 * end of each flow block */
4682 switch(cur_bank & 3) {
4686 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4689 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4690 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4693 insertBankSwitch(pos, pcprev, -1, -1);
4698 new_pc = newpCode(POC_BCF,
4699 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4700 pCodeInsertAfter(pcprev, new_pc);
4703 //fprintf(stderr, "Brute force switch\n");
4712 if(reg && REG_BANK(reg)!=cur_bank) {
4713 //fprintf(stderr,"need to switch banks\n");
4714 /* Examine the instruction before this one to make sure it is
4715 * not a skip type instruction */
4716 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4717 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4718 int b = cur_bank ^ REG_BANK(reg);
4720 cur_bank = REG_BANK(reg);
4726 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4729 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4730 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4734 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4735 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4737 insertBankSwitch(0, pc, -1, -1);
4746 void pBlockDestruct(pBlock *pb)
4757 /*-----------------------------------------------------------------*/
4758 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4759 /* name dbName and combine them */
4760 /* into one block */
4761 /*-----------------------------------------------------------------*/
4762 void mergepBlocks(char dbName)
4765 pBlock *pb, *pbmerged = NULL,*pbn;
4767 pb = the_pFile->pbHead;
4769 //fprintf(stderr," merging blocks named %c\n",dbName);
4773 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4774 if( getpBlock_dbName(pb) == dbName) {
4776 //fprintf(stderr," merged block %c\n",dbName);
4781 addpCode2pBlock(pbmerged, pb->pcHead);
4782 /* addpCode2pBlock doesn't handle the tail: */
4783 pbmerged->pcTail = pb->pcTail;
4785 pb->prev->next = pbn;
4787 pbn->prev = pb->prev;
4792 //printpBlock(stderr, pbmerged);
4799 /*-----------------------------------------------------------------*/
4800 /* AnalyzeFlow - Examine the flow of the code and optimize */
4802 /* level 0 == minimal optimization */
4803 /* optimize registers that are used only by two instructions */
4804 /* level 1 == maximal optimization */
4805 /* optimize by looking at pairs of instructions that use the */
4807 /*-----------------------------------------------------------------*/
4809 void AnalyzeFlow(int level)
4811 static int times_called=0;
4819 /* if this is not the first time this function has been called,
4820 then clean up old flow information */
4821 if(times_called++) {
4822 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4825 RegsUnMapLiveRanges();
4831 /* Phase 2 - Flow Analysis - Register Banking
4833 * In this phase, the individual flow blocks are examined
4834 * and register banking is fixed.
4837 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4838 //FixRegisterBanking(pb);
4840 /* Phase 2 - Flow Analysis
4842 * In this phase, the pCode is partition into pCodeFlow
4843 * blocks. The flow blocks mark the points where a continuous
4844 * stream of instructions changes flow (e.g. because of
4845 * a call or goto or whatever).
4848 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4852 /* Phase 2 - Flow Analysis - linking flow blocks
4854 * In this phase, the individual flow blocks are examined
4855 * to determine their order of excution.
4858 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4861 /* Phase 3 - Flow Analysis - Flow Tree
4863 * In this phase, the individual flow blocks are examined
4864 * to determine their order of excution.
4867 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4871 /* Phase x - Flow Analysis - Used Banks
4873 * In this phase, the individual flow blocks are examined
4874 * to determine the Register Banks they use
4877 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4881 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4882 pCodeRegMapLiveRanges(pb);
4884 RemoveUnusedRegisters();
4886 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4887 pCodeRegOptimizeRegUsage(level);
4893 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4897 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4899 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4900 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4901 pcflow = pcflow->next) {
4903 FillFlow(PCFL(pcflow));
4908 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4910 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4911 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4912 pcflow = pcflow->next) {
4914 FlowStats(PCFL(pcflow));
4920 /*-----------------------------------------------------------------*/
4921 /* AnalyzeBanking - Called after the memory addresses have been */
4922 /* assigned to the registers. */
4924 /*-----------------------------------------------------------------*/
4926 void AnalyzeBanking(void)
4930 if(!picIsInitialized()) {
4931 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4932 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4933 fprintf(stderr,"support/scripts/inc2h.pl\n");
4934 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4939 /* Phase x - Flow Analysis - Used Banks
4941 * In this phase, the individual flow blocks are examined
4942 * to determine the Register Banks they use
4948 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4950 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4951 FixRegisterBanking(pb);
4955 /*-----------------------------------------------------------------*/
4956 /* buildCallTree - look at the flow and extract all of the calls */
4958 /*-----------------------------------------------------------------*/
4959 set *register_usage(pBlock *pb);
4961 void buildCallTree(void )
4972 /* Now build the call tree.
4973 First we examine all of the pCodes for functions.
4974 Keep in mind that the function boundaries coincide
4975 with pBlock boundaries.
4977 The algorithm goes something like this:
4978 We have two nested loops. The outer loop iterates
4979 through all of the pBlocks/functions. The inner
4980 loop iterates through all of the pCodes for
4981 a given pBlock. When we begin iterating through
4982 a pBlock, the variable pc_fstart, pCode of the start
4983 of a function, is cleared. We then search for pCodes
4984 of type PC_FUNCTION. When one is encountered, we
4985 initialize pc_fstart to this and at the same time
4986 associate a new pBranch object that signifies a
4987 branch entry. If a return is found, then this signifies
4988 a function exit point. We'll link the pCodes of these
4989 returns to the matching pc_fstart.
4991 When we're done, a doubly linked list of pBranches
4992 will exist. The head of this list is stored in
4993 `the_pFile', which is the meta structure for all
4994 of the pCode. Look at the printCallTree function
4995 on how the pBranches are linked together.
4998 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4999 pCode *pc_fstart=NULL;
5000 for(pc = pb->pcHead; pc; pc = pc->next) {
5002 if (PCF(pc)->fname) {
5004 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5005 //fprintf(stderr," found main \n");
5006 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5010 pbr = Safe_calloc(1,sizeof(pBranch));
5011 pbr->pc = pc_fstart = pc;
5014 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5016 // Here's a better way of doing the same:
5017 addSet(&pb->function_entries, pc);
5020 // Found an exit point in a function, e.g. return
5021 // (Note, there may be more than one return per function)
5023 pBranchLink(PCF(pc_fstart), PCF(pc));
5025 addSet(&pb->function_exits, pc);
5027 } else if(isCALL(pc)) {
5028 addSet(&pb->function_calls,pc);
5033 /* Re-allocate the registers so that there are no collisions
5034 * between local variables when one function call another */
5037 // pic14_deallocateAllRegs();
5039 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5046 /*-----------------------------------------------------------------*/
5047 /* AnalyzepCode - parse the pCode that has been generated and form */
5048 /* all of the logical connections. */
5050 /* Essentially what's done here is that the pCode flow is */
5052 /*-----------------------------------------------------------------*/
5054 void AnalyzepCode(char dbName)
5065 /* Phase 1 - Register allocation and peep hole optimization
5067 * The first part of the analysis is to determine the registers
5068 * that are used in the pCode. Once that is done, the peep rules
5069 * are applied to the code. We continue to loop until no more
5070 * peep rule optimizations are found (or until we exceed the
5071 * MAX_PASSES threshold).
5073 * When done, the required registers will be determined.
5079 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5080 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5082 /* First, merge the labels with the instructions */
5083 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5084 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5086 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5087 //fprintf(stderr," analyze and merging block %c\n",dbName);
5088 pBlockMergeLabels(pb);
5091 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5095 changes = OptimizepCode(dbName);
5097 } while(changes && (i++ < MAX_PASSES));
5102 /*-----------------------------------------------------------------*/
5103 /* ispCodeFunction - returns true if *pc is the pCode of a */
5105 /*-----------------------------------------------------------------*/
5106 bool ispCodeFunction(pCode *pc)
5109 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5115 /*-----------------------------------------------------------------*/
5116 /* findFunction - Search for a function by name (given the name) */
5117 /* in the set of all functions that are in a pBlock */
5118 /* (note - I expect this to change because I'm planning to limit */
5119 /* pBlock's to just one function declaration */
5120 /*-----------------------------------------------------------------*/
5121 pCode *findFunction(char *fname)
5128 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5130 pc = setFirstItem(pb->function_entries);
5133 if((pc->type == PC_FUNCTION) &&
5135 (strcmp(fname, PCF(pc)->fname)==0))
5138 pc = setNextItem(pb->function_entries);
5146 void MarkUsedRegisters(set *regset)
5151 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5152 r2 = pic14_regWithIdx(r1->rIdx);
5158 void pBlockStats(FILE *of, pBlock *pb)
5164 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5166 // for now just print the first element of each set
5167 pc = setFirstItem(pb->function_entries);
5169 fprintf(of,";entry: ");
5172 pc = setFirstItem(pb->function_exits);
5174 fprintf(of,";has an exit\n");
5178 pc = setFirstItem(pb->function_calls);
5180 fprintf(of,";functions called:\n");
5183 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5184 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5186 pc = setNextItem(pb->function_calls);
5190 r = setFirstItem(pb->tregisters);
5192 int n = elementsInSet(pb->tregisters);
5194 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5197 fprintf(of,"; %s\n",r->name);
5198 r = setNextItem(pb->tregisters);
5203 /*-----------------------------------------------------------------*/
5204 /*-----------------------------------------------------------------*/
5206 static void sequencepCode(void)
5212 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5214 pb->seq = GpCodeSequenceNumber+1;
5216 for( pc = pb->pcHead; pc; pc = pc->next)
5217 pc->seq = ++GpCodeSequenceNumber;
5223 /*-----------------------------------------------------------------*/
5224 /*-----------------------------------------------------------------*/
5225 set *register_usage(pBlock *pb)
5228 set *registers=NULL;
5229 set *registersInCallPath = NULL;
5231 /* check recursion */
5233 pc = setFirstItem(pb->function_entries);
5240 if(pc->type != PC_FUNCTION)
5241 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5243 pc = setFirstItem(pb->function_calls);
5244 for( ; pc; pc = setNextItem(pb->function_calls)) {
5246 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5247 char *dest = get_op_from_instruction(PCI(pc));
5249 pcn = findFunction(dest);
5251 registersInCallPath = register_usage(pcn->pb);
5253 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5258 pBlockStats(stderr,pb); // debug
5261 // Mark the registers in this block as used.
5263 MarkUsedRegisters(pb->tregisters);
5264 if(registersInCallPath) {
5265 /* registers were used in the functions this pBlock has called */
5266 /* so now, we need to see if these collide with the ones we are */
5269 regs *r1,*r2, *newreg;
5271 DFPRINTF((stderr,"comparing registers\n"));
5273 r1 = setFirstItem(registersInCallPath);
5276 r2 = setFirstItem(pb->tregisters);
5278 while(r2 && (r1->type != REG_STK)) {
5280 if(r2->rIdx == r1->rIdx) {
5281 newreg = pic14_findFreeReg(REG_GPR);
5285 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5289 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5290 r1->rIdx, newreg->rIdx));
5291 r2->rIdx = newreg->rIdx;
5292 //if(r2->name) free(r2->name);
5294 r2->name = Safe_strdup(newreg->name);
5298 newreg->wasUsed = 1;
5300 r2 = setNextItem(pb->tregisters);
5303 r1 = setNextItem(registersInCallPath);
5306 /* Collisions have been resolved. Now free the registers in the call path */
5307 r1 = setFirstItem(registersInCallPath);
5309 if(r1->type != REG_STK) {
5310 newreg = pic14_regWithIdx(r1->rIdx);
5313 r1 = setNextItem(registersInCallPath);
5317 // MarkUsedRegisters(pb->registers);
5319 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5322 DFPRINTF((stderr,"returning regs\n"));
5324 DFPRINTF((stderr,"not returning regs\n"));
5326 DFPRINTF((stderr,"pBlock after register optim.\n"));
5327 pBlockStats(stderr,pb); // debug
5333 /*-----------------------------------------------------------------*/
5334 /* printCallTree - writes the call tree to a file */
5336 /*-----------------------------------------------------------------*/
5337 void pct2(FILE *of,pBlock *pb,int indent)
5341 // set *registersInCallPath = NULL;
5347 return; //recursion ?
5349 pc = setFirstItem(pb->function_entries);
5356 for(i=0;i<indent;i++) // Indentation
5359 if(pc->type == PC_FUNCTION)
5360 fprintf(of,"%s\n",PCF(pc)->fname);
5365 pc = setFirstItem(pb->function_calls);
5366 for( ; pc; pc = setNextItem(pb->function_calls)) {
5368 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5369 char *dest = get_op_from_instruction(PCI(pc));
5371 pcn = findFunction(dest);
5373 pct2(of,pcn->pb,indent+1);
5375 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5383 /*-----------------------------------------------------------------*/
5384 /* printCallTree - writes the call tree to a file */
5386 /*-----------------------------------------------------------------*/
5388 void printCallTree(FILE *of)
5400 fprintf(of, "\npBlock statistics\n");
5401 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5406 fprintf(of,"Call Tree\n");
5407 pbr = the_pFile->functions;
5411 if(!ispCodeFunction(pc))
5412 fprintf(of,"bug in call tree");
5415 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5417 while(pc->next && !ispCodeFunction(pc->next)) {
5419 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5420 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5428 fprintf(of,"\n**************\n\na better call tree\n");
5429 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5434 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5435 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5441 /*-----------------------------------------------------------------*/
5443 /*-----------------------------------------------------------------*/
5445 void InlineFunction(pBlock *pb)
5453 pc = setFirstItem(pb->function_calls);
5455 for( ; pc; pc = setNextItem(pb->function_calls)) {
5458 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5464 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5466 //fprintf(stderr,"Cool can inline:\n");
5467 //pcn->print(stderr,pcn);
5469 //fprintf(stderr,"recursive call Inline\n");
5470 InlineFunction(pcn->pb);
5471 //fprintf(stderr,"return from recursive call Inline\n");
5474 At this point, *pc points to a CALL mnemonic, and
5475 *pcn points to the function that is being called.
5477 To in-line this call, we need to remove the CALL
5478 and RETURN(s), and link the function pCode in with
5484 /* Remove the CALL */
5488 /* remove callee pBlock from the pBlock linked list */
5489 removepBlock(pcn->pb);
5497 /* Remove the Function pCode */
5498 pct = findNextInstruction(pcn->next);
5500 /* Link the function with the callee */
5501 pc->next = pcn->next;
5502 pcn->next->prev = pc;
5504 /* Convert the function name into a label */
5506 pbr = Safe_calloc(1,sizeof(pBranch));
5507 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5509 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5510 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5512 /* turn all of the return's except the last into goto's */
5513 /* check case for 2 instruction pBlocks */
5514 pce = findNextInstruction(pcn->next);
5516 pCode *pce_next = findNextInstruction(pce->next);
5518 if(pce_next == NULL) {
5519 /* found the last return */
5520 pCode *pc_call_next = findNextInstruction(pc_call->next);
5522 //fprintf(stderr,"found last return\n");
5523 //pce->print(stderr,pce);
5524 pce->prev->next = pc_call->next;
5525 pc_call->next->prev = pce->prev;
5526 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5536 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5542 /*-----------------------------------------------------------------*/
5544 /*-----------------------------------------------------------------*/
5546 void InlinepCode(void)
5555 if(!functionInlining)
5558 /* Loop through all of the function definitions and count the
5559 * number of times each one is called */
5560 //fprintf(stderr,"inlining %d\n",__LINE__);
5562 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5564 pc = setFirstItem(pb->function_calls);
5566 for( ; pc; pc = setNextItem(pb->function_calls)) {
5569 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5570 if(pcn && isPCF(pcn)) {
5571 PCF(pcn)->ncalled++;
5574 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5579 //fprintf(stderr,"inlining %d\n",__LINE__);
5581 /* Now, Loop through the function definitions again, but this
5582 * time inline those functions that have only been called once. */
5584 InlineFunction(the_pFile->pbHead);
5585 //fprintf(stderr,"inlining %d\n",__LINE__);
5587 for(pb = the_pFile->pbHead; pb; pb = pb->next)