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 = 0; /* 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,int 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
140 (PCC_W | PCC_REGISTER), // inCond
141 (PCC_REGISTER | PCC_Z) // outCond
144 pCodeInstruction pciADDFW = {
145 {PC_OPCODE, NULL, NULL, 0, NULL,
158 0,0, // dest, bit instruction
161 (PCC_W | PCC_REGISTER), // inCond
162 (PCC_W | PCC_Z) // outCond
165 pCodeInstruction pciADDLW = {
166 {PC_OPCODE, NULL, NULL, 0, NULL,
179 0,0, // dest, bit instruction
182 (PCC_W | PCC_LITERAL), // inCond
183 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
186 pCodeInstruction pciANDLW = {
187 {PC_OPCODE, NULL, NULL, 0, NULL,
200 0,0, // dest, bit instruction
203 (PCC_W | PCC_LITERAL), // inCond
204 (PCC_W | PCC_Z) // outCond
207 pCodeInstruction pciANDWF = {
208 {PC_OPCODE, NULL, NULL, 0, NULL,
221 1,0, // dest, bit instruction
224 (PCC_W | PCC_REGISTER), // inCond
225 (PCC_REGISTER | PCC_Z) // outCond
228 pCodeInstruction pciANDFW = {
229 {PC_OPCODE, NULL, NULL, 0, NULL,
242 0,0, // dest, bit instruction
245 (PCC_W | PCC_REGISTER), // inCond
246 (PCC_W | PCC_Z) // outCond
249 pCodeInstruction pciBCF = {
250 {PC_OPCODE, NULL, NULL, 0, NULL,
263 1,1, // dest, bit instruction
266 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
267 PCC_REGISTER // outCond
270 pCodeInstruction pciBSF = {
271 {PC_OPCODE, NULL, NULL, 0, NULL,
284 1,1, // dest, bit instruction
287 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
288 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
291 pCodeInstruction pciBTFSC = {
292 {PC_OPCODE, NULL, NULL, 0, NULL,
305 0,1, // dest, bit instruction
308 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
309 PCC_EXAMINE_PCOP // outCond
312 pCodeInstruction pciBTFSS = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,1, // dest, bit instruction
329 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
330 PCC_EXAMINE_PCOP // outCond
333 pCodeInstruction pciCALL = {
334 {PC_OPCODE, NULL, NULL, 0, NULL,
347 0,0, // dest, bit instruction
354 pCodeInstruction pciCOMF = {
355 {PC_OPCODE, NULL, NULL, 0, NULL,
368 1,0, // dest, bit instruction
371 PCC_REGISTER, // inCond
372 PCC_REGISTER // outCond
375 pCodeInstruction pciCOMFW = {
376 {PC_OPCODE, NULL, NULL, 0, NULL,
389 0,0, // dest, bit instruction
392 PCC_REGISTER, // inCond
396 pCodeInstruction pciCLRF = {
397 {PC_OPCODE, NULL, NULL, 0, NULL,
410 0,0, // dest, bit instruction
414 PCC_REGISTER // outCond
417 pCodeInstruction pciCLRW = {
418 {PC_OPCODE, NULL, NULL, 0, NULL,
431 0,0, // dest, bit instruction
438 pCodeInstruction pciCLRWDT = {
439 {PC_OPCODE, NULL, NULL, 0, NULL,
452 0,0, // dest, bit instruction
459 pCodeInstruction pciDECF = {
460 {PC_OPCODE, NULL, NULL, 0, NULL,
473 1,0, // dest, bit instruction
476 PCC_REGISTER, // inCond
477 PCC_REGISTER // outCond
480 pCodeInstruction pciDECFW = {
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 0,0, // dest, bit instruction
497 PCC_REGISTER, // inCond
501 pCodeInstruction pciDECFSZ = {
502 {PC_OPCODE, NULL, NULL, 0, NULL,
515 1,0, // dest, bit instruction
518 PCC_REGISTER, // inCond
519 PCC_REGISTER // outCond
522 pCodeInstruction pciDECFSZW = {
523 {PC_OPCODE, NULL, NULL, 0, NULL,
536 0,0, // dest, bit instruction
539 PCC_REGISTER, // inCond
543 pCodeInstruction pciGOTO = {
544 {PC_OPCODE, NULL, NULL, 0, NULL,
557 0,0, // dest, bit instruction
564 pCodeInstruction pciINCF = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 1,0, // dest, bit instruction
581 PCC_REGISTER, // inCond
582 PCC_REGISTER // outCond
585 pCodeInstruction pciINCFW = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 0,0, // dest, bit instruction
602 PCC_REGISTER, // inCond
606 pCodeInstruction pciINCFSZ = {
607 {PC_OPCODE, NULL, NULL, 0, NULL,
620 1,0, // dest, bit instruction
623 PCC_REGISTER, // inCond
624 PCC_REGISTER // outCond
627 pCodeInstruction pciINCFSZW = {
628 {PC_OPCODE, NULL, NULL, 0, NULL,
641 0,0, // dest, bit instruction
644 PCC_REGISTER, // inCond
648 pCodeInstruction pciIORWF = {
649 {PC_OPCODE, NULL, NULL, 0, NULL,
662 1,0, // dest, bit instruction
665 (PCC_W | PCC_REGISTER), // inCond
666 (PCC_REGISTER | PCC_Z) // outCond
669 pCodeInstruction pciIORFW = {
670 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,0, // dest, bit instruction
686 (PCC_W | PCC_REGISTER), // inCond
687 (PCC_W | PCC_Z) // outCond
690 pCodeInstruction pciIORLW = {
691 {PC_OPCODE, NULL, NULL, 0, NULL,
704 0,0, // dest, bit instruction
707 (PCC_W | PCC_LITERAL), // inCond
708 (PCC_W | PCC_Z) // outCond
711 pCodeInstruction pciMOVF = {
712 {PC_OPCODE, NULL, NULL, 0, NULL,
725 1,0, // dest, bit instruction
728 PCC_REGISTER, // inCond
732 pCodeInstruction pciMOVFW = {
733 {PC_OPCODE, NULL, NULL, 0, NULL,
746 0,0, // dest, bit instruction
749 PCC_REGISTER, // inCond
750 (PCC_W | PCC_Z) // outCond
753 pCodeInstruction pciMOVWF = {
754 {PC_OPCODE, NULL, NULL, 0, NULL,
767 0,0, // dest, bit instruction
771 PCC_REGISTER // outCond
774 pCodeInstruction pciMOVLW = {
775 {PC_OPCODE, NULL, NULL, 0, NULL,
788 0,0, // dest, bit instruction
791 (PCC_NONE | PCC_LITERAL), // inCond
795 pCodeInstruction pciNOP = {
796 {PC_OPCODE, NULL, NULL, 0, NULL,
808 0,0, // dest, bit instruction
815 pCodeInstruction pciRETFIE = {
816 {PC_OPCODE, NULL, NULL, 0, NULL,
829 0,0, // dest, bit instruction
833 PCC_NONE // outCond (not true... affects the GIE bit too)
836 pCodeInstruction pciRETLW = {
837 {PC_OPCODE, NULL, NULL, 0, NULL,
850 0,0, // dest, bit instruction
853 PCC_LITERAL, // inCond
857 pCodeInstruction pciRETURN = {
858 {PC_OPCODE, NULL, NULL, 0, NULL,
871 0,0, // dest, bit instruction
878 pCodeInstruction pciRLF = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 1,0, // dest, bit instruction
895 (PCC_C | PCC_REGISTER), // inCond
896 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
899 pCodeInstruction pciRLFW = {
900 {PC_OPCODE, NULL, NULL, 0, NULL,
913 0,0, // dest, bit instruction
916 (PCC_C | PCC_REGISTER), // inCond
917 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
920 pCodeInstruction pciRRF = {
921 {PC_OPCODE, NULL, NULL, 0, NULL,
934 1,0, // dest, bit instruction
937 (PCC_C | PCC_REGISTER), // inCond
938 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
941 pCodeInstruction pciRRFW = {
942 {PC_OPCODE, NULL, NULL, 0, NULL,
955 0,0, // dest, bit instruction
958 (PCC_C | PCC_REGISTER), // inCond
959 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
962 pCodeInstruction pciSUBWF = {
963 {PC_OPCODE, NULL, NULL, 0, NULL,
976 1,0, // dest, bit instruction
979 (PCC_W | PCC_REGISTER), // inCond
980 (PCC_REGISTER | PCC_Z) // outCond
983 pCodeInstruction pciSUBFW = {
984 {PC_OPCODE, NULL, NULL, 0, NULL,
997 0,0, // dest, bit instruction
1000 (PCC_W | PCC_REGISTER), // inCond
1001 (PCC_W | PCC_Z) // outCond
1004 pCodeInstruction pciSUBLW = {
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 0,0, // dest, bit instruction
1019 0,0, // branch, skip
1021 (PCC_W | PCC_LITERAL), // inCond
1022 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1025 pCodeInstruction pciSWAPF = {
1026 {PC_OPCODE, NULL, NULL, 0, NULL,
1032 NULL, // from branch
1039 1,0, // dest, bit instruction
1040 0,0, // branch, skip
1042 (PCC_REGISTER), // inCond
1043 (PCC_REGISTER) // outCond
1046 pCodeInstruction pciSWAPFW = {
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 0,0, // branch, skip
1063 (PCC_REGISTER), // inCond
1067 pCodeInstruction pciTRIS = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 0,0, // dest, bit instruction
1082 0,0, // branch, skip
1085 PCC_REGISTER // outCond
1088 pCodeInstruction pciXORWF = {
1089 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 1,0, // dest, bit instruction
1103 0,0, // branch, skip
1105 (PCC_W | PCC_REGISTER), // inCond
1106 (PCC_REGISTER | PCC_Z) // outCond
1109 pCodeInstruction pciXORFW = {
1110 {PC_OPCODE, NULL, NULL, 0, NULL,
1116 NULL, // from branch
1123 0,0, // dest, bit instruction
1124 0,0, // branch, skip
1126 (PCC_W | PCC_REGISTER), // inCond
1127 (PCC_W | PCC_Z) // outCond
1130 pCodeInstruction pciXORLW = {
1131 {PC_OPCODE, NULL, NULL, 0, NULL,
1137 NULL, // from branch
1144 0,0, // dest, bit instruction
1145 0,0, // branch, skip
1147 (PCC_W | PCC_LITERAL), // inCond
1148 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1152 #define MAX_PIC14MNEMONICS 100
1153 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1155 /* This definition needs to be part of configure.in */
1156 // #define USE_VSNPRINTF
1158 #ifdef USE_VSNPRINTF
1159 // Alas, vsnprintf is not ANSI standard, and does not exist
1160 // on Solaris (and probably other non-Gnu flavored Unixes).
1162 /*-----------------------------------------------------------------*/
1163 /* SAFE_snprintf - like snprintf except the string pointer is */
1164 /* after the string has been printed to. This is */
1165 /* useful for printing to string as though if it */
1166 /* were a stream. */
1167 /*-----------------------------------------------------------------*/
1168 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1176 va_start(val, format);
1178 vsnprintf(*str, *size, format, val);
1184 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1185 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1193 #else // USE_VSNPRINTF
1195 // This version is *not* safe, despite the name.
1197 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1201 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1206 va_start(val, format);
1208 vsprintf(buffer, format, val);
1211 len = strlen(buffer);
1213 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1214 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1217 strcpy(*str, buffer);
1223 #endif // USE_VSNPRINTF
1226 extern void initStack(int base_address, int size);
1227 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1228 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1229 extern void init_pic(char *);
1231 void pCodeInitRegisters(void)
1233 static int initialized=0;
1239 initStack(0xfff, 8);
1240 init_pic(port->processor);
1242 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1243 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1244 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1245 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1246 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1247 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1249 pc_status.rIdx = IDX_STATUS;
1250 pc_fsr.rIdx = IDX_FSR;
1251 pc_indf.rIdx = IDX_INDF;
1252 pc_intcon.rIdx = IDX_INTCON;
1253 pc_pcl.rIdx = IDX_PCL;
1254 pc_pclath.rIdx = IDX_PCLATH;
1256 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1257 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1258 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1260 pc_kzero.rIdx = IDX_KZ;
1261 pc_wsave.rIdx = IDX_WSAVE;
1262 pc_ssave.rIdx = IDX_SSAVE;
1264 /* probably should put this in a separate initialization routine */
1265 pb_dead_pcodes = newpBlock();
1269 /*-----------------------------------------------------------------*/
1270 /* mnem2key - convert a pic mnemonic into a hash key */
1271 /* (BTW - this spreads the mnemonics quite well) */
1273 /*-----------------------------------------------------------------*/
1275 int mnem2key(char const *mnem)
1284 key += toupper(*mnem++) +1;
1288 return (key & 0x1f);
1292 void pic14initMnemonics(void)
1297 pCodeInstruction *pci;
1299 if(mnemonics_initialized)
1302 //FIXME - probably should NULL out the array before making the assignments
1303 //since we check the array contents below this initialization.
1305 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1306 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1307 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1308 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1309 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1310 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1311 pic14Mnemonics[POC_BCF] = &pciBCF;
1312 pic14Mnemonics[POC_BSF] = &pciBSF;
1313 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1314 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1315 pic14Mnemonics[POC_CALL] = &pciCALL;
1316 pic14Mnemonics[POC_COMF] = &pciCOMF;
1317 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1318 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1319 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1320 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1321 pic14Mnemonics[POC_DECF] = &pciDECF;
1322 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1323 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1324 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1325 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1326 pic14Mnemonics[POC_INCF] = &pciINCF;
1327 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1328 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1329 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1330 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1331 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1332 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1333 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1334 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1335 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1336 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1337 pic14Mnemonics[POC_NOP] = &pciNOP;
1338 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1339 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1340 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1341 pic14Mnemonics[POC_RLF] = &pciRLF;
1342 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1343 pic14Mnemonics[POC_RRF] = &pciRRF;
1344 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1345 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1346 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1347 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1348 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1349 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1350 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1351 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1352 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1353 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1355 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1356 if(pic14Mnemonics[i])
1357 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1358 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1361 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1362 pci = hTabNextItem(pic14MnemonicsHash, &key);
1365 mnemonics_initialized = 1;
1368 int getpCodePeepCommand(char *cmd);
1370 int getpCode(char *mnem,unsigned dest)
1373 pCodeInstruction *pci;
1374 int key = mnem2key(mnem);
1376 if(!mnemonics_initialized)
1377 pic14initMnemonics();
1379 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1383 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1384 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1388 pci = hTabNextItemWK (pic14MnemonicsHash);
1395 /*-----------------------------------------------------------------*
1396 * pic14initpCodePeepCommands
1398 *-----------------------------------------------------------------*/
1399 void pic14initpCodePeepCommands(void)
1407 hTabAddItem(&pic14pCodePeepCommandsHash,
1408 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1410 } while (peepCommands[i].cmd);
1412 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1415 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1416 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1421 /*-----------------------------------------------------------------
1424 *-----------------------------------------------------------------*/
1426 int getpCodePeepCommand(char *cmd)
1430 int key = mnem2key(cmd);
1433 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1436 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1437 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1441 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1448 char getpBlock_dbName(pBlock *pb)
1454 return pb->cmemmap->dbName;
1458 void pBlockConvert2ISR(pBlock *pb)
1469 /*-----------------------------------------------------------------*/
1470 /* movepBlock2Head - given the dbname of a pBlock, move all */
1471 /* instances to the front of the doubly linked */
1472 /* list of pBlocks */
1473 /*-----------------------------------------------------------------*/
1475 void movepBlock2Head(char dbName)
1479 pb = the_pFile->pbHead;
1483 if(getpBlock_dbName(pb) == dbName) {
1484 pBlock *pbn = pb->next;
1485 pb->next = the_pFile->pbHead;
1486 the_pFile->pbHead->prev = pb;
1487 the_pFile->pbHead = pb;
1490 pb->prev->next = pbn;
1492 // If the pBlock that we just moved was the last
1493 // one in the link of all of the pBlocks, then we
1494 // need to point the tail to the block just before
1495 // the one we moved.
1496 // Note: if pb->next is NULL, then pb must have
1497 // been the last pBlock in the chain.
1500 pbn->prev = pb->prev;
1502 the_pFile->pbTail = pb->prev;
1513 void copypCode(FILE *of, char dbName)
1517 if(!of || !the_pFile)
1520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1521 if(getpBlock_dbName(pb) == dbName) {
1528 void pcode_test(void)
1531 DFPRINTF((stderr,"pcode is alive!\n"));
1541 /* create the file name */
1542 strcpy(buffer,srcFileName);
1543 strcat(buffer,".p");
1545 if( !(pFile = fopen(buffer, "w" ))) {
1546 werror(E_FILE_OPEN_ERR,buffer);
1550 fprintf(pFile,"pcode dump\n\n");
1552 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1553 fprintf(pFile,"\n\tNew pBlock\n\n");
1555 fprintf(pFile,"%s",pb->cmemmap->sname);
1557 fprintf(pFile,"internal pblock");
1559 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1560 printpBlock(pFile,pb);
1564 /*-----------------------------------------------------------------*/
1565 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1566 /* ister, RegCond will return the bit being referenced. */
1568 /* fixme - why not just OR in the pcop bit field */
1569 /*-----------------------------------------------------------------*/
1571 static int RegCond(pCodeOp *pcop)
1577 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1578 switch(PCORB(pcop)->bit) {
1592 /*-----------------------------------------------------------------*/
1593 /* newpCode - create and return a newly initialized pCode */
1595 /* fixme - rename this */
1597 /* The purpose of this routine is to create a new Instruction */
1598 /* pCode. This is called by gen.c while the assembly code is being */
1602 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1603 /* (note that the op is analogous to but not the */
1604 /* same thing as the opcode of the instruction.) */
1605 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1608 /* a pointer to the new malloc'd pCode is returned. */
1612 /*-----------------------------------------------------------------*/
1613 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1615 pCodeInstruction *pci ;
1617 if(!mnemonics_initialized)
1618 pic14initMnemonics();
1620 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1622 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1623 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1626 if(pci->inCond & PCC_EXAMINE_PCOP)
1627 pci->inCond |= RegCond(pcop);
1629 if(pci->outCond & PCC_EXAMINE_PCOP)
1630 pci->outCond |= RegCond(pcop);
1632 pci->pc.prev = pci->pc.next = NULL;
1633 return (pCode *)pci;
1636 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1642 /*-----------------------------------------------------------------*/
1643 /* newpCodeWild - create a "wild" as in wild card pCode */
1645 /* Wild pcodes are used during the peep hole optimizer to serve */
1646 /* as place holders for any instruction. When a snippet of code is */
1647 /* compared to a peep hole rule, the wild card opcode will match */
1648 /* any instruction. However, the optional operand and label are */
1649 /* additional qualifiers that must also be matched before the */
1650 /* line (of assembly code) is declared matched. Note that the */
1651 /* operand may be wild too. */
1653 /* Note, a wild instruction is specified just like a wild var: */
1654 /* %4 ; A wild instruction, */
1655 /* See the peeph.def file for additional examples */
1657 /*-----------------------------------------------------------------*/
1659 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1664 pcw = Safe_calloc(1,sizeof(pCodeWild));
1666 pcw->pci.pc.type = PC_WILD;
1667 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1668 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1669 pcw->pci.pc.pb = NULL;
1671 // pcw->pci.pc.analyze = genericAnalyze;
1672 pcw->pci.pc.destruct = genericDestruct;
1673 pcw->pci.pc.print = genericPrint;
1675 pcw->id = pCodeID; // this is the 'n' in %n
1676 pcw->operand = optional_operand;
1677 pcw->label = optional_label;
1679 pcw->mustBeBitSkipInst = 0;
1680 pcw->mustNotBeBitSkipInst = 0;
1681 pcw->invertBitSkipInst = 0;
1683 return ( (pCode *)pcw);
1687 /*-----------------------------------------------------------------*/
1688 /* newPcodeInlineP - create a new pCode from a char string */
1689 /*-----------------------------------------------------------------*/
1692 pCode *newpCodeInlineP(char *cP)
1697 pcc = Safe_calloc(1,sizeof(pCodeComment));
1699 pcc->pc.type = PC_INLINE;
1700 pcc->pc.prev = pcc->pc.next = NULL;
1701 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1704 // pcc->pc.analyze = genericAnalyze;
1705 pcc->pc.destruct = genericDestruct;
1706 pcc->pc.print = genericPrint;
1709 pcc->comment = Safe_strdup(cP);
1711 pcc->comment = NULL;
1713 return ( (pCode *)pcc);
1717 /*-----------------------------------------------------------------*/
1718 /* newPcodeCharP - create a new pCode from a char string */
1719 /*-----------------------------------------------------------------*/
1721 pCode *newpCodeCharP(char *cP)
1726 pcc = Safe_calloc(1,sizeof(pCodeComment));
1728 pcc->pc.type = PC_COMMENT;
1729 pcc->pc.prev = pcc->pc.next = NULL;
1730 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1733 // pcc->pc.analyze = genericAnalyze;
1734 pcc->pc.destruct = genericDestruct;
1735 pcc->pc.print = genericPrint;
1738 pcc->comment = Safe_strdup(cP);
1740 pcc->comment = NULL;
1742 return ( (pCode *)pcc);
1746 /*-----------------------------------------------------------------*/
1747 /* newpCodeFunction - */
1748 /*-----------------------------------------------------------------*/
1751 pCode *newpCodeFunction(char *mod,char *f)
1755 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1756 //_ALLOC(pcf,sizeof(pCodeFunction));
1758 pcf->pc.type = PC_FUNCTION;
1759 pcf->pc.prev = pcf->pc.next = NULL;
1760 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1763 // pcf->pc.analyze = genericAnalyze;
1764 pcf->pc.destruct = genericDestruct;
1765 pcf->pc.print = pCodePrintFunction;
1770 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1771 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1772 strcpy(pcf->modname,mod);
1774 pcf->modname = NULL;
1777 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1778 pcf->fname = Safe_calloc(1,strlen(f)+1);
1779 strcpy(pcf->fname,f);
1783 return ( (pCode *)pcf);
1787 /*-----------------------------------------------------------------*/
1789 /*-----------------------------------------------------------------*/
1790 void destructpCodeFlow(pCode *pc)
1792 if(!pc || !isPCFL(pc))
1801 deleteSet(&PCFL(pc)->registers);
1802 deleteSet(&PCFL(pc)->from);
1803 deleteSet(&PCFL(pc)->to);
1808 pCode *newpCodeFlow(void )
1812 //_ALLOC(pcflow,sizeof(pCodeFlow));
1813 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1815 pcflow->pc.type = PC_FLOW;
1816 pcflow->pc.prev = pcflow->pc.next = NULL;
1817 pcflow->pc.pb = NULL;
1819 // pcflow->pc.analyze = genericAnalyze;
1820 pcflow->pc.destruct = destructpCodeFlow;
1821 pcflow->pc.print = genericPrint;
1823 pcflow->pc.seq = GpcFlowSeq++;
1825 pcflow->from = pcflow->to = NULL;
1827 pcflow->inCond = PCC_NONE;
1828 pcflow->outCond = PCC_NONE;
1830 pcflow->firstBank = -1;
1831 pcflow->lastBank = -1;
1833 pcflow->FromConflicts = 0;
1834 pcflow->ToConflicts = 0;
1838 pcflow->registers = newSet();
1840 return ( (pCode *)pcflow);
1844 /*-----------------------------------------------------------------*/
1845 /*-----------------------------------------------------------------*/
1846 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1848 pCodeFlowLink *pcflowLink;
1850 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1852 pcflowLink->pcflow = pcflow;
1853 pcflowLink->bank_conflict = 0;
1858 /*-----------------------------------------------------------------*/
1859 /* newpCodeCSource - create a new pCode Source Symbol */
1860 /*-----------------------------------------------------------------*/
1862 pCode *newpCodeCSource(int ln, char *f, char *l)
1867 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1869 pccs->pc.type = PC_CSOURCE;
1870 pccs->pc.prev = pccs->pc.next = NULL;
1873 pccs->pc.destruct = genericDestruct;
1874 pccs->pc.print = genericPrint;
1876 pccs->line_number = ln;
1878 pccs->line = Safe_strdup(l);
1883 pccs->file_name = Safe_strdup(f);
1885 pccs->file_name = NULL;
1887 return ( (pCode *)pccs);
1890 /*-----------------------------------------------------------------*/
1891 /* pCodeLabelDestruct - free memory used by a label. */
1892 /*-----------------------------------------------------------------*/
1893 static void pCodeLabelDestruct(pCode *pc)
1899 if((pc->type == PC_LABEL) && PCL(pc)->label)
1900 free(PCL(pc)->label);
1906 pCode *newpCodeLabel(char *name, int key)
1912 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1914 pcl->pc.type = PC_LABEL;
1915 pcl->pc.prev = pcl->pc.next = NULL;
1916 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1919 // pcl->pc.analyze = genericAnalyze;
1920 pcl->pc.destruct = pCodeLabelDestruct;
1921 pcl->pc.print = pCodePrintLabel;
1927 sprintf(s,"_%05d_DS_",key);
1932 pcl->label = Safe_strdup(s);
1935 return ( (pCode *)pcl);
1940 /*-----------------------------------------------------------------*/
1941 /* newpBlock - create and return a pointer to a new pBlock */
1942 /*-----------------------------------------------------------------*/
1943 pBlock *newpBlock(void)
1948 PpB = Safe_calloc(1,sizeof(pBlock) );
1949 PpB->next = PpB->prev = NULL;
1951 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1952 PpB->tregisters = NULL;
1954 PpB->FlowTree = NULL;
1960 /*-----------------------------------------------------------------*/
1961 /* newpCodeChain - create a new chain of pCodes */
1962 /*-----------------------------------------------------------------*
1964 * This function will create a new pBlock and the pointer to the
1965 * pCode that is passed in will be the first pCode in the block.
1966 *-----------------------------------------------------------------*/
1969 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1972 pBlock *pB = newpBlock();
1974 pB->pcHead = pB->pcTail = pc;
1981 /*-----------------------------------------------------------------*/
1982 /* newpCodeOpLabel - Create a new label given the key */
1983 /* Note, a negative key means that the label is part of wild card */
1984 /* (and hence a wild card label) used in the pCodePeep */
1985 /* optimizations). */
1986 /*-----------------------------------------------------------------*/
1988 pCodeOp *newpCodeOpLabel(char *name, int key)
1991 static int label_key=-1;
1995 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1996 pcop->type = PO_LABEL;
2001 sprintf(s=buffer,"_%05d_DS_",key);
2003 s = name, key = label_key--;
2006 pcop->name = Safe_strdup(s);
2008 ((pCodeOpLabel *)pcop)->key = key;
2013 /*-----------------------------------------------------------------*/
2014 /*-----------------------------------------------------------------*/
2015 pCodeOp *newpCodeOpLit(int lit)
2021 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2022 pcop->type = PO_LITERAL;
2026 sprintf(s,"0x%02x",lit);
2028 pcop->name = Safe_strdup(s);
2031 ((pCodeOpLit *)pcop)->lit = lit;
2036 /*-----------------------------------------------------------------*/
2037 /*-----------------------------------------------------------------*/
2038 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2042 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2043 pcop->type = PO_IMMEDIATE;
2045 regs *r = dirregWithName(name);
2046 pcop->name = Safe_strdup(name);
2049 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2050 PCOI(pcop)->rIdx = r->rIdx;
2052 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2053 PCOI(pcop)->rIdx = -1;
2055 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2060 PCOI(pcop)->index = index;
2061 PCOI(pcop)->offset = offset;
2062 PCOI(pcop)->_const = code_space;
2067 /*-----------------------------------------------------------------*/
2068 /*-----------------------------------------------------------------*/
2069 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2075 if(!pcwb || !subtype) {
2076 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2080 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2081 pcop->type = PO_WILD;
2082 sprintf(s,"%%%d",id);
2083 pcop->name = Safe_strdup(s);
2085 PCOW(pcop)->id = id;
2086 PCOW(pcop)->pcwb = pcwb;
2087 PCOW(pcop)->subtype = subtype;
2088 PCOW(pcop)->matched = NULL;
2093 /*-----------------------------------------------------------------*/
2094 /*-----------------------------------------------------------------*/
2095 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2099 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2100 pcop->type = PO_GPR_BIT;
2102 pcop->name = Safe_strdup(s);
2106 PCORB(pcop)->bit = bit;
2107 PCORB(pcop)->inBitSpace = inBitSpace;
2109 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2110 PCOR(pcop)->r = NULL;
2111 PCOR(pcop)->rIdx = 0;
2115 /*-----------------------------------------------------------------*
2116 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2118 * If rIdx >=0 then a specific register from the set of registers
2119 * will be selected. If rIdx <0, then a new register will be searched
2121 *-----------------------------------------------------------------*/
2123 pCodeOp *newpCodeOpReg(int rIdx)
2127 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2132 PCOR(pcop)->rIdx = rIdx;
2133 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2135 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2138 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2141 pcop->type = PCOR(pcop)->r->pc_type;
2146 pCodeOp *newpCodeOpRegFromStr(char *name)
2150 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2151 PCOR(pcop)->r = allocRegByName(name, 1);
2152 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2153 pcop->type = PCOR(pcop)->r->pc_type;
2154 pcop->name = PCOR(pcop)->r->name;
2159 /*-----------------------------------------------------------------*/
2160 /*-----------------------------------------------------------------*/
2162 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2169 pcop = newpCodeOpBit(name, -1,0);
2173 pcop = newpCodeOpLit(-1);
2177 pcop = newpCodeOpLabel(NULL,-1);
2180 pcop = newpCodeOpReg(-1);
2183 case PO_GPR_REGISTER:
2185 pcop = newpCodeOpRegFromStr(name);
2187 pcop = newpCodeOpReg(-1);
2191 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2194 pcop->name = Safe_strdup(name);
2202 /*-----------------------------------------------------------------*/
2203 /*-----------------------------------------------------------------*/
2204 void pCodeConstString(char *name, char *value)
2208 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2213 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2217 sprintf(buffer,"; %s = %s",name,value);
2219 addpCode2pBlock(pb,newpCodeCharP(buffer));
2220 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2223 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2229 /*-----------------------------------------------------------------*/
2230 /*-----------------------------------------------------------------*/
2231 void pCodeReadCodeTable(void)
2235 fprintf(stderr, " %s\n",__FUNCTION__);
2237 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2241 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2242 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2243 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2244 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2246 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2247 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2248 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2249 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2254 /*-----------------------------------------------------------------*/
2255 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2256 /*-----------------------------------------------------------------*/
2257 void addpCode2pBlock(pBlock *pb, pCode *pc)
2264 /* If this is the first pcode to be added to a block that
2265 * was initialized with a NULL pcode, then go ahead and
2266 * make this pcode the head and tail */
2267 pb->pcHead = pb->pcTail = pc;
2270 pb->pcTail->next = pc;
2272 pc->prev = pb->pcTail;
2279 /*-----------------------------------------------------------------*/
2280 /* addpBlock - place a pBlock into the pFile */
2281 /*-----------------------------------------------------------------*/
2282 void addpBlock(pBlock *pb)
2284 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2287 /* First time called, we'll pass through here. */
2288 //_ALLOC(the_pFile,sizeof(pFile));
2289 the_pFile = Safe_calloc(1,sizeof(pFile));
2290 the_pFile->pbHead = the_pFile->pbTail = pb;
2291 the_pFile->functions = NULL;
2295 the_pFile->pbTail->next = pb;
2296 pb->prev = the_pFile->pbTail;
2298 the_pFile->pbTail = pb;
2301 /*-----------------------------------------------------------------*/
2302 /* removepBlock - remove a pBlock from the pFile */
2303 /*-----------------------------------------------------------------*/
2304 void removepBlock(pBlock *pb)
2312 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2314 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2317 if(pbs == the_pFile->pbHead)
2318 the_pFile->pbHead = pbs->next;
2320 if (pbs == the_pFile->pbTail)
2321 the_pFile->pbTail = pbs->prev;
2324 pbs->next->prev = pbs->prev;
2327 pbs->prev->next = pbs->next;
2334 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2338 /*-----------------------------------------------------------------*/
2339 /* printpCode - write the contents of a pCode to a file */
2340 /*-----------------------------------------------------------------*/
2341 void printpCode(FILE *of, pCode *pc)
2352 fprintf(of,"warning - unable to print pCode\n");
2355 /*-----------------------------------------------------------------*/
2356 /* printpBlock - write the contents of a pBlock to a file */
2357 /*-----------------------------------------------------------------*/
2358 void printpBlock(FILE *of, pBlock *pb)
2368 for(pc = pb->pcHead; pc; pc = pc->next)
2373 /*-----------------------------------------------------------------*/
2375 /* pCode processing */
2379 /*-----------------------------------------------------------------*/
2381 void unlinkpCode(pCode *pc)
2387 fprintf(stderr,"Unlinking: ");
2388 printpCode(stderr, pc);
2391 pc->prev->next = pc->next;
2393 pc->next->prev = pc->prev;
2395 pc->prev = pc->next = NULL;
2399 /*-----------------------------------------------------------------*/
2400 /*-----------------------------------------------------------------*/
2402 static void genericDestruct(pCode *pc)
2408 /* For instructions, tell the register (if there's one used)
2409 * that it's no longer needed */
2410 regs *reg = getRegFromInstruction(pc);
2412 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2415 /* Instead of deleting the memory used by this pCode, mark
2416 * the object as bad so that if there's a pointer to this pCode
2417 * dangling around somewhere then (hopefully) when the type is
2418 * checked we'll catch it.
2423 addpCode2pBlock(pb_dead_pcodes, pc);
2430 /*-----------------------------------------------------------------*/
2431 /*-----------------------------------------------------------------*/
2432 void pBlockRegs(FILE *of, pBlock *pb)
2437 r = setFirstItem(pb->tregisters);
2439 r = setNextItem(pb->tregisters);
2444 /*-----------------------------------------------------------------*/
2445 /*-----------------------------------------------------------------*/
2446 char *get_op(pCodeOp *pcop,char *buffer, int size)
2451 int use_buffer = 1; // copy the string to the passed buffer pointer
2456 use_buffer = 0; // Don't bother copying the string to the buffer.
2460 switch(pcop->type) {
2464 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2467 return PCOR(pcop)->r->name;
2470 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2473 SAFE_snprintf(&buffer,&size,"%s",r->name);
2483 if(PCOI(pcop)->_const) {
2485 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2486 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2489 8 * PCOI(pcop)->offset );
2491 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2494 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2495 SAFE_snprintf(&s,&size,"(%s + %d)",
2497 PCOI(pcop)->index );
2499 SAFE_snprintf(&s,&size,"%s",pcop->name);
2506 //size = sizeof(buffer);
2507 if( PCOR(pcop)->instance) {
2508 SAFE_snprintf(&s,&size,"(%s + %d)",
2510 PCOR(pcop)->instance );
2511 //fprintf(stderr,"PO_DIR %s\n",buffer);
2513 SAFE_snprintf(&s,&size,"%s",pcop->name);
2519 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2528 return "NO operand";
2532 /*-----------------------------------------------------------------*/
2533 /*-----------------------------------------------------------------*/
2534 static char *get_op_from_instruction( pCodeInstruction *pcc)
2538 return get_op(pcc->pcop,NULL,0);
2540 return ("ERROR Null: "__FUNCTION__);
2544 /*-----------------------------------------------------------------*/
2545 /*-----------------------------------------------------------------*/
2546 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2549 fprintf(of,"pcodeopprint- not implemented\n");
2552 /*-----------------------------------------------------------------*/
2553 /*-----------------------------------------------------------------*/
2554 char *pCode2str(char *str, int size, pCode *pc)
2562 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2564 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2566 if(PCI(pc)->isBitInst) {
2567 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2568 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2569 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2570 PCI(pc)->pcop->name ,
2571 PCI(pc)->pcop->name );
2573 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2574 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2575 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2576 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2578 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2579 //PCI(pc)->pcop->t.bit );
2582 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2583 if( PCI(pc)->num_ops == 2)
2584 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2586 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2589 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2591 if( PCI(pc)->num_ops == 2)
2592 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2600 /* assuming that comment ends with a \n */
2601 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2605 /* assuming that inline code ends with a \n */
2606 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2610 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2613 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2616 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2619 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2622 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2626 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2633 /*-----------------------------------------------------------------*/
2634 /* genericPrint - the contents of a pCode to a file */
2635 /*-----------------------------------------------------------------*/
2636 static void genericPrint(FILE *of, pCode *pc)
2644 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2648 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2652 // If the opcode has a label, print that first
2654 pBranch *pbl = PCI(pc)->label;
2655 while(pbl && pbl->pc) {
2656 if(pbl->pc->type == PC_LABEL)
2657 pCodePrintLabel(of, pbl->pc);
2663 genericPrint(of,PCODE(PCI(pc)->cline));
2668 pCode2str(str, 256, pc);
2670 fprintf(of,"%s",str);
2674 fprintf(of, "\t;key=%03x",pc->seq);
2676 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2681 pBranch *dpb = pc->to; // debug
2683 switch ( dpb->pc->type) {
2685 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2688 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2691 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2694 fprintf(of, "\t;flow");
2708 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2709 if(PCW(pc)->pci.label)
2710 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2712 if(PCW(pc)->operand) {
2713 fprintf(of,";\toperand ");
2714 pCodeOpPrint(of,PCW(pc)->operand );
2720 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2721 if(PCFL(pc)->ancestor)
2722 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2729 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2733 fprintf(of,"unknown pCode type %d\n",pc->type);
2738 /*-----------------------------------------------------------------*/
2739 /* pCodePrintFunction - prints function begin/end */
2740 /*-----------------------------------------------------------------*/
2742 static void pCodePrintFunction(FILE *of, pCode *pc)
2748 if( ((pCodeFunction *)pc)->modname)
2749 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2751 if(PCF(pc)->fname) {
2752 pBranch *exits = PCF(pc)->to;
2754 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2757 exits = exits->next;
2760 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2763 if((PCF(pc)->from &&
2764 PCF(pc)->from->pc->type == PC_FUNCTION &&
2765 PCF(PCF(pc)->from->pc)->fname) )
2766 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2768 fprintf(of,"; exit point [can't find entry point]\n");
2771 /*-----------------------------------------------------------------*/
2772 /* pCodePrintLabel - prints label */
2773 /*-----------------------------------------------------------------*/
2775 static void pCodePrintLabel(FILE *of, pCode *pc)
2782 fprintf(of,"%s\n",PCL(pc)->label);
2783 else if (PCL(pc)->key >=0)
2784 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2786 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2789 /*-----------------------------------------------------------------*/
2790 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2791 /* remove it if it is found. */
2792 /*-----------------------------------------------------------------*/
2793 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2800 if(pcl->type == PC_OPCODE)
2801 b = PCI(pcl)->label;
2803 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2808 //fprintf (stderr, "%s \n",__FUNCTION__);
2809 //pcl->print(stderr,pcl);
2810 //pc->print(stderr,pc);
2813 //fprintf (stderr, "found label\n");
2817 bprev->next = b->next; /* Not first pCode in chain */
2821 PCI(pcl)->label = b->next; /* First pCode in chain */
2824 return; /* A label can't occur more than once */
2832 /*-----------------------------------------------------------------*/
2833 /*-----------------------------------------------------------------*/
2834 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2853 /*-----------------------------------------------------------------*/
2854 /* pBranchLink - given two pcodes, this function will link them */
2855 /* together through their pBranches */
2856 /*-----------------------------------------------------------------*/
2857 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2861 // Declare a new branch object for the 'from' pCode.
2863 //_ALLOC(b,sizeof(pBranch));
2864 b = Safe_calloc(1,sizeof(pBranch));
2865 b->pc = PCODE(t); // The link to the 'to' pCode.
2868 f->to = pBranchAppend(f->to,b);
2870 // Now do the same for the 'to' pCode.
2872 //_ALLOC(b,sizeof(pBranch));
2873 b = Safe_calloc(1,sizeof(pBranch));
2877 t->from = pBranchAppend(t->from,b);
2882 /*-----------------------------------------------------------------*/
2883 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2885 /*-----------------------------------------------------------------*/
2886 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2899 /*-----------------------------------------------------------------*/
2900 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2901 /*-----------------------------------------------------------------*/
2902 static void pCodeUnlink(pCode *pc)
2907 if(!pc->prev || !pc->next) {
2908 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2912 /* first remove the pCode from the chain */
2913 pc->prev->next = pc->next;
2914 pc->next->prev = pc->prev;
2916 /* Now for the hard part... */
2918 /* Remove the branches */
2922 pc1 = pb1->pc; /* Get the pCode that branches to the
2923 * one we're unlinking */
2925 /* search for the link back to this pCode (the one we're
2927 if(pb2 = pBranchFind(pc1->to,pc)) {
2928 pb2->pc = pc->to->pc; // make the replacement
2930 /* if the pCode we're unlinking contains multiple 'to'
2931 * branches (e.g. this a skip instruction) then we need
2932 * to copy these extra branches to the chain. */
2934 pBranchAppend(pb2, pc->to->next);
2943 /*-----------------------------------------------------------------*/
2944 /*-----------------------------------------------------------------*/
2946 static void genericAnalyze(pCode *pc)
2956 // Go through the pCodes that are in pCode chain and link
2957 // them together through the pBranches. Note, the pCodes
2958 // are linked together as a contiguous stream like the
2959 // assembly source code lines. The linking here mimics this
2960 // except that comments are not linked in.
2962 pCode *npc = pc->next;
2964 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2965 pBranchLink(pc,npc);
2970 /* reached the end of the pcode chain without finding
2971 * an instruction we could link to. */
2975 fprintf(stderr,"analyze PC_FLOW\n");
2979 fprintf(stderr,,";A bad pCode is being used\n");
2985 /*-----------------------------------------------------------------*/
2986 /*-----------------------------------------------------------------*/
2987 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2991 if(pc->type == PC_LABEL) {
2992 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2995 if(pc->type == PC_OPCODE) {
2996 pbr = PCI(pc)->label;
2998 if(pbr->pc->type == PC_LABEL) {
2999 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3009 /*-----------------------------------------------------------------*/
3010 /*-----------------------------------------------------------------*/
3011 int checkLabel(pCode *pc)
3015 if(pc && isPCI(pc)) {
3016 pbr = PCI(pc)->label;
3018 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3028 /*-----------------------------------------------------------------*/
3029 /* findLabelinpBlock - Search the pCode for a particular label */
3030 /*-----------------------------------------------------------------*/
3031 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3038 for(pc = pb->pcHead; pc; pc = pc->next)
3039 if(compareLabel(pc,pcop_label))
3045 /*-----------------------------------------------------------------*/
3046 /* findLabel - Search the pCode for a particular label */
3047 /*-----------------------------------------------------------------*/
3048 pCode * findLabel(pCodeOpLabel *pcop_label)
3056 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3057 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3061 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3065 /*-----------------------------------------------------------------*/
3066 /* findNextpCode - given a pCode, find the next of type 'pct' */
3067 /* in the linked list */
3068 /*-----------------------------------------------------------------*/
3069 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3082 /*-----------------------------------------------------------------*/
3083 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3084 /* in the linked list */
3085 /*-----------------------------------------------------------------*/
3086 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3098 /*-----------------------------------------------------------------*/
3099 /* findNextInstruction - given a pCode, find the next instruction */
3100 /* in the linked list */
3101 /*-----------------------------------------------------------------*/
3102 pCode * findNextInstruction(pCode *pci)
3107 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3111 fprintf(stderr,"findNextInstruction: ");
3112 printpCode(stderr, pc);
3117 //fprintf(stderr,"Couldn't find instruction\n");
3121 /*-----------------------------------------------------------------*/
3122 /* findNextInstruction - given a pCode, find the next instruction */
3123 /* in the linked list */
3124 /*-----------------------------------------------------------------*/
3125 pCode * findPrevInstruction(pCode *pci)
3127 return findPrevpCode(pci, PC_OPCODE);
3130 /*-----------------------------------------------------------------*/
3131 /* findFunctionEnd - given a pCode find the end of the function */
3132 /* that contains it */
3133 /*-----------------------------------------------------------------*/
3134 pCode * findFunctionEnd(pCode *pc)
3138 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3144 fprintf(stderr,"Couldn't find function end\n");
3149 /*-----------------------------------------------------------------*/
3150 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3151 /* instruction with which it is associated. */
3152 /*-----------------------------------------------------------------*/
3153 static void AnalyzeLabel(pCode *pc)
3162 static void AnalyzeGOTO(pCode *pc)
3165 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3169 static void AnalyzeSKIP(pCode *pc)
3172 pBranchLink(pc,findNextInstruction(pc->next));
3173 pBranchLink(pc,findNextInstruction(pc->next->next));
3177 static void AnalyzeRETURN(pCode *pc)
3180 // branch_link(pc,findFunctionEnd(pc->next));
3186 /*-----------------------------------------------------------------*/
3187 /*-----------------------------------------------------------------*/
3188 regs * getRegFromInstruction(pCode *pc)
3194 PCI(pc)->num_ops == 0 )
3197 switch(PCI(pc)->pcop->type) {
3200 return PCOR(PCI(pc)->pcop)->r;
3202 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3206 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3207 return PCOR(PCI(pc)->pcop)->r;
3210 if(PCOI(PCI(pc)->pcop)->r)
3211 return (PCOI(PCI(pc)->pcop)->r);
3213 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3214 return dirregWithName(PCI(pc)->pcop->name);
3215 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3218 return PCOR(PCI(pc)->pcop)->r;
3221 //fprintf(stderr, "getRegFromInstruction - dir\n");
3222 return PCOR(PCI(pc)->pcop)->r;
3224 //fprintf(stderr, "getRegFromInstruction - literal\n");
3228 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3229 //genericPrint(stderr, pc);
3237 /*-----------------------------------------------------------------*/
3238 /*-----------------------------------------------------------------*/
3240 void AnalyzepBlock(pBlock *pb)
3247 /* Find all of the registers used in this pBlock
3248 * by looking at each instruction and examining it's
3251 for(pc = pb->pcHead; pc; pc = pc->next) {
3253 /* Is this an instruction with operands? */
3254 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3256 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3258 /* Loop through all of the registers declared so far in
3259 this block and see if we find this one there */
3261 regs *r = setFirstItem(pb->tregisters);
3264 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3265 PCOR(PCI(pc)->pcop)->r = r;
3268 r = setNextItem(pb->tregisters);
3272 /* register wasn't found */
3273 //r = Safe_calloc(1, sizeof(regs));
3274 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3275 //addSet(&pb->tregisters, r);
3276 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3277 //PCOR(PCI(pc)->pcop)->r = r;
3278 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3280 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3283 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3284 if(PCOR(PCI(pc)->pcop)->r) {
3285 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3286 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3288 if(PCI(pc)->pcop->name)
3289 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3291 fprintf(stderr,"ERROR: NULL register\n");
3300 /*-----------------------------------------------------------------*/
3302 /*-----------------------------------------------------------------*/
3303 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3305 void InsertpFlow(pCode *pc, pCode **pflow)
3308 PCFL(*pflow)->end = pc;
3310 if(!pc || !pc->next)
3313 *pflow = newpCodeFlow();
3314 pCodeInsertAfter(pc, *pflow);
3317 /*-----------------------------------------------------------------*/
3318 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3319 /* the flow blocks. */
3321 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3322 * point the instruction flow changes.
3324 /*-----------------------------------------------------------------*/
3325 void BuildFlow(pBlock *pb)
3328 pCode *last_pci=NULL;
3335 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3336 /* Insert a pCodeFlow object at the beginning of a pBlock */
3338 InsertpFlow(pb->pcHead, &pflow);
3340 //pflow = newpCodeFlow(); /* Create a new Flow object */
3341 //pflow->next = pb->pcHead; /* Make the current head the next object */
3342 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3343 //pb->pcHead = pflow; /* Make the Flow object the head */
3346 for( pc = findNextInstruction(pb->pcHead);
3348 pc=findNextInstruction(pc)) {
3351 PCI(pc)->pcflow = PCFL(pflow);
3353 //fprintf(stderr," build: ");
3354 //pflow->print(stderr,pflow);
3356 if( PCI(pc)->isSkip) {
3358 /* The two instructions immediately following this one
3359 * mark the beginning of a new flow segment */
3361 while(pc && PCI(pc)->isSkip) {
3363 PCI(pc)->pcflow = PCFL(pflow);
3367 InsertpFlow(pc, &pflow);
3368 pc=findNextInstruction(pc->next);
3376 PCI(pc)->pcflow = PCFL(pflow);
3378 InsertpFlow(pc, &pflow);
3380 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3382 InsertpFlow(pc, &pflow);
3385 } else if (checkLabel(pc)) {
3387 /* This instruction marks the beginning of a
3388 * new flow segment */
3393 /* If the previous pCode is not a flow object, then
3394 * insert a new flow object. (This check prevents
3395 * two consecutive flow objects from being insert in
3396 * the case where a skip instruction preceeds an
3397 * instruction containing a label.) */
3399 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3400 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3402 PCI(pc)->pcflow = PCFL(pflow);
3409 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3411 PCFL(pflow)->end = pb->pcTail;
3414 /*-------------------------------------------------------------------*/
3415 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3416 /* the flow blocks. */
3418 * unBuildFlow removes pCodeFlow objects from a pCode chain
3420 /*-----------------------------------------------------------------*/
3421 void unBuildFlow(pBlock *pb)
3436 if(PCI(pc)->pcflow) {
3437 //free(PCI(pc)->pcflow);
3438 PCI(pc)->pcflow = NULL;
3441 } else if(isPCFL(pc) )
3450 /*-----------------------------------------------------------------*/
3451 /*-----------------------------------------------------------------*/
3452 void dumpCond(int cond)
3455 static char *pcc_str[] = {
3469 int ncond = sizeof(pcc_str) / sizeof(char *);
3472 fprintf(stderr, "0x%04X\n",cond);
3474 for(i=0,j=1; i<ncond; i++, j<<=1)
3476 fprintf(stderr, " %s\n",pcc_str[i]);
3480 /*-----------------------------------------------------------------*/
3481 /*-----------------------------------------------------------------*/
3482 void FlowStats(pCodeFlow *pcflow)
3490 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3492 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3495 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3500 fprintf(stderr, " FlowStats inCond: ");
3501 dumpCond(pcflow->inCond);
3502 fprintf(stderr, " FlowStats outCond: ");
3503 dumpCond(pcflow->outCond);
3507 /*-----------------------------------------------------------------*
3508 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3509 * if it affects the banking bits.
3511 * return: -1 == Banking bits are unaffected by this pCode.
3513 * return: > 0 == Banking bits are affected.
3515 * If the banking bits are affected, then the returned value describes
3516 * which bits are affected and how they're affected. The lower half
3517 * of the integer maps to the bits that are affected, the upper half
3518 * to whether they're set or cleared.
3520 *-----------------------------------------------------------------*/
3521 #define SET_BANK_BIT (1 << 16)
3522 #define CLR_BANK_BIT 0
3524 int isBankInstruction(pCode *pc)
3532 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3534 /* Check to see if the register banks are changing */
3535 if(PCI(pc)->isModReg) {
3537 pCodeOp *pcop = PCI(pc)->pcop;
3538 switch(PCI(pc)->op) {
3541 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3542 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3543 return SET_BANK_BIT | PIC_RP0_BIT;
3546 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3547 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3548 return CLR_BANK_BIT | PIC_RP0_BIT;
3553 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3554 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3555 return CLR_BANK_BIT | PIC_RP1_BIT;
3557 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3558 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3559 return CLR_BANK_BIT | PIC_RP1_BIT;
3563 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3564 //genericPrint(stderr, pc);
3575 /*-----------------------------------------------------------------*/
3576 /*-----------------------------------------------------------------*/
3577 void FillFlow(pCodeFlow *pcflow)
3586 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3588 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3591 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3598 isBankInstruction(pc);
3600 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3604 fprintf(stderr, " FillFlow - Bad end of flow\n");
3606 fprintf(stderr, " FillFlow - Ending flow with\n ");
3607 pc->print(stderr,pc);
3610 fprintf(stderr, " FillFlow inCond: ");
3611 dumpCond(pcflow->inCond);
3612 fprintf(stderr, " FillFlow outCond: ");
3613 dumpCond(pcflow->outCond);
3617 /*-----------------------------------------------------------------*/
3618 /*-----------------------------------------------------------------*/
3619 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3621 pCodeFlowLink *fromLink, *toLink;
3623 if(!from || !to || !to->pcflow || !from->pcflow)
3626 fromLink = newpCodeFlowLink(from->pcflow);
3627 toLink = newpCodeFlowLink(to->pcflow);
3629 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3630 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3634 /*-----------------------------------------------------------------*
3635 * void LinkFlow(pBlock *pb)
3637 * In BuildFlow, the PIC code has been partitioned into contiguous
3638 * non-branching segments. In LinkFlow, we determine the execution
3639 * order of these segments. For example, if one of the segments ends
3640 * with a skip, then we know that there are two possible flow segments
3641 * to which control may be passed.
3642 *-----------------------------------------------------------------*/
3643 void LinkFlow(pBlock *pb)
3649 //fprintf(stderr,"linkflow \n");
3651 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3653 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3656 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3658 //fprintf(stderr," link: ");
3659 //pcflow->print(stderr,pcflow);
3661 //FillFlow(PCFL(pcflow));
3663 pc = PCFL(pcflow)->end;
3665 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3666 if(isPCI_SKIP(pc)) {
3667 //fprintf(stderr, "ends with skip\n");
3668 //pc->print(stderr,pc);
3669 pct=findNextInstruction(pc->next);
3670 LinkFlow_pCode(PCI(pc),PCI(pct));
3671 pct=findNextInstruction(pct->next);
3672 LinkFlow_pCode(PCI(pc),PCI(pct));
3676 if(isPCI_BRANCH(pc)) {
3677 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3679 //fprintf(stderr, "ends with branch\n ");
3680 //pc->print(stderr,pc);
3682 if(!(pcol && isPCOLAB(pcol))) {
3683 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3684 pc->print(stderr,pc);
3685 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3690 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3691 LinkFlow_pCode(PCI(pc),PCI(pct));
3693 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3699 //fprintf(stderr, "ends with non-branching instruction:\n");
3700 //pc->print(stderr,pc);
3702 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3708 //fprintf(stderr, "ends with unknown\n");
3709 //pc->print(stderr,pc);
3713 //fprintf(stderr, "ends with nothing: ERROR\n");
3717 /*-----------------------------------------------------------------*/
3718 /*-----------------------------------------------------------------*/
3720 /*-----------------------------------------------------------------*/
3721 /*-----------------------------------------------------------------*/
3722 int isPCinFlow(pCode *pc, pCode *pcflow)
3728 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3731 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3737 /*-----------------------------------------------------------------*/
3738 /*-----------------------------------------------------------------*/
3739 void BanksUsedFlow2(pCode *pcflow)
3748 if(!isPCFL(pcflow)) {
3749 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3753 pc = findNextInstruction(pcflow->next);
3755 PCFL(pcflow)->lastBank = -1;
3757 while(isPCinFlow(pc,pcflow)) {
3759 int bank_selected = isBankInstruction(pc);
3761 //if(PCI(pc)->pcflow)
3762 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3764 if(bank_selected > 0) {
3765 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3767 /* This instruction is modifying banking bits before accessing registers */
3769 PCFL(pcflow)->firstBank = -1;
3771 if(PCFL(pcflow)->lastBank == -1)
3772 PCFL(pcflow)->lastBank = 0;
3774 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3775 if(bank_selected & SET_BANK_BIT)
3776 PCFL(pcflow)->lastBank |= bank;
3780 reg = getRegFromInstruction(pc);
3782 if(reg && !isREGinBank(reg, bank)) {
3783 int allbanks = REGallBanks(reg);
3785 PCFL(pcflow)->firstBank = allbanks;
3787 PCFL(pcflow)->lastBank = allbanks;
3794 pc = findNextInstruction(pc->next);
3797 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3798 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3803 /*-----------------------------------------------------------------*/
3804 /*-----------------------------------------------------------------*/
3805 void BanksUsedFlow(pBlock *pb)
3810 //pb->pcHead->print(stderr, pb->pcHead);
3812 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3813 //pcflow->print(stderr,pcflow);
3815 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3817 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3819 BanksUsedFlow2(pcflow);
3825 /*-----------------------------------------------------------------*/
3826 /*-----------------------------------------------------------------*/
3827 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3835 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3837 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3838 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3841 /* insert the bank switch after this pc instruction */
3842 pCode *pcnext = findNextInstruction(pc);
3843 pCodeInsertAfter(pc, new_pc);
3848 pCodeInsertAfter(pc->prev, new_pc);
3850 /* Move the label, if there is one */
3852 if(PCI(pc)->label) {
3853 PCI(new_pc)->label = PCI(pc)->label;
3854 PCI(pc)->label = NULL;
3857 /* The new instruction has the same pcflow block */
3858 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3861 /*-----------------------------------------------------------------*/
3862 /*-----------------------------------------------------------------*/
3863 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3874 pc = findNextInstruction(pcfl->pc.next);
3876 while(isPCinFlow(pc,PCODE(pcfl))) {
3879 reg = getRegFromInstruction(pc);
3882 fprintf(stderr, " %s ",reg->name);
3883 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3888 if(reg && REG_BANK(reg)!=cur_bank) {
3889 /* Examine the instruction before this one to make sure it is
3890 * not a skip type instruction */
3891 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3892 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3893 int b = cur_bank ^ REG_BANK(reg);
3895 //fprintf(stderr, "Cool! can switch banks\n");
3896 cur_bank = REG_BANK(reg);
3901 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3904 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3905 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3909 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3910 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3912 insertBankSwitch(0, pc, -1, -1);
3915 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3916 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3917 pCodeInsertAfter(pc->prev, new_pc);
3918 if(PCI(pc)->label) {
3919 PCI(new_pc)->label = PCI(pc)->label;
3920 PCI(pc)->label = NULL;
3924 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3925 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3926 pCodeInsertAfter(pc, new_pc);
3932 //fprintf(stderr, "Bummer can't switch banks\n");
3938 pc = findNextInstruction(pc->next);
3942 if(pcprev && cur_bank) {
3943 /* Brute force - make sure that we point to bank 0 at the
3944 * end of each flow block */
3945 new_pc = newpCode(POC_BCF,
3946 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3947 pCodeInsertAfter(pcprev, new_pc);
3953 /*-----------------------------------------------------------------*/
3954 /*int compareBankFlow - compare the banking requirements between */
3956 /*-----------------------------------------------------------------*/
3957 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3960 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3963 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3966 if(pcflow->firstBank == -1)
3970 if(pcflowLink->pcflow->firstBank == -1) {
3971 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3972 pcflowLink->pcflow->to :
3973 pcflowLink->pcflow->from);
3974 return compareBankFlow(pcflow, pctl, toORfrom);
3978 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3981 pcflowLink->bank_conflict++;
3982 pcflowLink->pcflow->FromConflicts++;
3983 pcflow->ToConflicts++;
3986 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3989 pcflowLink->bank_conflict++;
3990 pcflowLink->pcflow->ToConflicts++;
3991 pcflow->FromConflicts++;
3995 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3996 pcflowLink->pcflow->pc.seq,
3997 pcflowLink->pcflow->FromConflicts,
3998 pcflowLink->pcflow->ToConflicts);
4003 /*-----------------------------------------------------------------*/
4004 /*-----------------------------------------------------------------*/
4005 void FixBankFlow(pBlock *pb)
4009 pCodeFlowLink *pcfl;
4011 pCode *pcflow_max_To=NULL;
4012 pCode *pcflow_max_From=NULL;
4013 int max_ToConflicts=0;
4014 int max_FromConflicts=0;
4016 //fprintf(stderr,"Fix Bank flow \n");
4017 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4021 First loop through all of the flow objects in this pcode block
4022 and fix the ones that have banking conflicts between the
4026 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4028 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4030 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4032 if(!isPCFL(pcflow)) {
4033 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4037 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4038 PCFL(pcflow)->firstBank >= 0 &&
4039 PCFL(pcflow)->lastBank >= 0 ) {
4041 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4042 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4044 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4045 BanksUsedFlow2(pcflow);
4050 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4052 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4054 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4059 if(!isPCFL(pcflow)) {
4060 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4064 PCFL(pcflow)->FromConflicts = 0;
4065 PCFL(pcflow)->ToConflicts = 0;
4070 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4071 pcfl = setFirstItem(PCFL(pcflow)->from);
4074 pc = PCODE(pcfl->pcflow);
4077 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4078 pc->print(stderr,pc);
4081 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4084 pcfl=setNextItem(PCFL(pcflow)->from);
4087 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4088 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4090 FixRegisterBankingInFlow(PCFL(pcflow),0);
4091 BanksUsedFlow2(pcflow);
4093 continue; /* Don't need to check the flow from here - it's already been fixed */
4100 pcfl = setFirstItem(PCFL(pcflow)->to);
4103 pc = PCODE(pcfl->pcflow);
4105 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4106 pc->print(stderr,pc);
4109 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4112 pcfl=setNextItem(PCFL(pcflow)->to);
4115 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4116 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4118 FixRegisterBankingInFlow(PCFL(pcflow),0);
4119 BanksUsedFlow2(pcflow);
4124 Loop through the flow objects again and find the ones with the
4128 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4130 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4132 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4133 pcflow_max_To = pcflow;
4135 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4136 pcflow_max_From = pcflow;
4140 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4141 PCFL(pcflow_max_To)->pc.seq,
4142 PCFL(pcflow_max_To)->ToConflicts);
4145 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4146 PCFL(pcflow_max_From)->pc.seq,
4147 PCFL(pcflow_max_From)->FromConflicts);
4151 /*-----------------------------------------------------------------*/
4152 /*-----------------------------------------------------------------*/
4153 void DumpFlow(pBlock *pb)
4157 pCodeFlowLink *pcfl;
4160 fprintf(stderr,"Dump flow \n");
4161 pb->pcHead->print(stderr, pb->pcHead);
4163 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4164 pcflow->print(stderr,pcflow);
4166 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4168 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4170 if(!isPCFL(pcflow)) {
4171 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4174 fprintf(stderr,"dumping: ");
4175 pcflow->print(stderr,pcflow);
4176 FlowStats(PCFL(pcflow));
4178 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4180 pc = PCODE(pcfl->pcflow);
4182 fprintf(stderr, " from seq %d:\n",pc->seq);
4184 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4185 pc->print(stderr,pc);
4190 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4192 pc = PCODE(pcfl->pcflow);
4194 fprintf(stderr, " to seq %d:\n",pc->seq);
4196 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4197 pc->print(stderr,pc);
4206 /*-----------------------------------------------------------------*/
4207 /*-----------------------------------------------------------------*/
4208 int OptimizepBlock(pBlock *pb)
4213 if(!pb || !peepOptimizing)
4216 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4218 for(pc = pb->pcHead; pc; pc = pc->next)
4219 matches += pCodePeepMatchRule(pc);
4222 pc = findNextInstruction(pb->pcHead);
4230 if(pCodePeepMatchRule(pc)) {
4235 pc = findNextInstruction(pcprev->next);
4237 pc = findNextInstruction(pb->pcHead);
4239 pc = findNextInstruction(pc->next);
4243 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4248 /*-----------------------------------------------------------------*/
4249 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4250 /*-----------------------------------------------------------------*/
4251 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4255 for(pc = pcs; pc; pc = pc->next) {
4257 if((pc->type == PC_OPCODE) &&
4259 (PCI(pc)->pcop->type == PO_LABEL) &&
4260 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4268 /*-----------------------------------------------------------------*/
4269 /*-----------------------------------------------------------------*/
4270 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4275 (PCI(pc)->pcop->type == PO_LABEL)) {
4277 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4279 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4281 free(pcol->pcop.name);
4283 sprintf(buffer,"_%05d_DS_",pcl->key);
4285 pcol->pcop.name = Safe_strdup(buffer);
4286 pcol->key = pcl->key;
4287 //pc->print(stderr,pc);
4294 /*-----------------------------------------------------------------*/
4295 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4296 /* pCode chain if they're not used. */
4297 /*-----------------------------------------------------------------*/
4298 void pBlockRemoveUnusedLabels(pBlock *pb)
4300 pCode *pc; pCodeLabel *pcl;
4305 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4307 pBranch *pbr = PCI(pc)->label;
4308 if(pbr && pbr->next) {
4309 pCode *pcd = pb->pcHead;
4311 //fprintf(stderr, "multiple labels\n");
4312 //pc->print(stderr,pc);
4317 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4318 //fprintf(stderr,"Used by:\n");
4319 //pcd->print(stderr,pcd);
4321 exchangeLabels(PCL(pbr->pc),pcd);
4330 for(pc = pb->pcHead; pc; pc = pc->next) {
4332 if(isPCL(pc)) // pc->type == PC_LABEL)
4334 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4335 pcl = PCL(PCI(pc)->label->pc);
4338 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4340 /* This pCode is a label, so search the pBlock to see if anyone
4343 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4344 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4345 /* Couldn't find an instruction that refers to this label
4346 * So, unlink the pCode label from it's pCode chain
4347 * and destroy the label */
4348 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4350 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4351 if(pc->type == PC_LABEL) {
4353 pCodeLabelDestruct(pc);
4355 unlinkpCodeFromBranch(pc, PCODE(pcl));
4356 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4367 /*-----------------------------------------------------------------*/
4368 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4369 /* chain and put them into pBranches that are */
4370 /* associated with the appropriate pCode */
4372 /*-----------------------------------------------------------------*/
4373 void pBlockMergeLabels(pBlock *pb)
4376 pCode *pc, *pcnext=NULL;
4381 /* First, Try to remove any unused labels */
4382 //pBlockRemoveUnusedLabels(pb);
4384 /* Now loop through the pBlock and merge the labels with the opcodes */
4387 // for(pc = pb->pcHead; pc; pc = pc->next) {
4390 pCode *pcn = pc->next;
4392 if(pc->type == PC_LABEL) {
4394 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4395 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4396 if((pcnext = findNextInstruction(pc) )) {
4398 // Unlink the pCode label from it's pCode chain
4401 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4402 // And link it into the instruction's pBranch labels. (Note, since
4403 // it's possible to have multiple labels associated with one instruction
4404 // we must provide a means to accomodate the additional labels. Thus
4405 // the labels are placed into the singly-linked list "label" as
4406 // opposed to being a single member of the pCodeInstruction.)
4408 //_ALLOC(pbr,sizeof(pBranch));
4409 pbr = Safe_calloc(1,sizeof(pBranch));
4413 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4416 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4418 } else if(pc->type == PC_CSOURCE) {
4420 /* merge the source line symbolic info into the next instruction */
4421 if((pcnext = findNextInstruction(pc) )) {
4423 // Unlink the pCode label from it's pCode chain
4425 PCI(pcnext)->cline = PCCS(pc);
4426 //fprintf(stderr, "merging CSRC\n");
4427 //genericPrint(stderr,pcnext);
4433 pBlockRemoveUnusedLabels(pb);
4437 /*-----------------------------------------------------------------*/
4438 /*-----------------------------------------------------------------*/
4439 int OptimizepCode(char dbName)
4441 #define MAX_PASSES 4
4450 DFPRINTF((stderr," Optimizing pCode\n"));
4454 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4455 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4456 matches += OptimizepBlock(pb);
4459 while(matches && ++passes < MAX_PASSES);
4464 /*-----------------------------------------------------------------*/
4465 /* popCopyGPR2Bit - copy a pcode operator */
4466 /*-----------------------------------------------------------------*/
4468 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4472 pcop = newpCodeOpBit(pc->name, bitval, 0);
4474 if( !( (pcop->type == PO_LABEL) ||
4475 (pcop->type == PO_LITERAL) ||
4476 (pcop->type == PO_STR) ))
4477 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4485 /*-----------------------------------------------------------------*/
4486 /*-----------------------------------------------------------------*/
4487 int InstructionRegBank(pCode *pc)
4491 if( (reg = getRegFromInstruction(pc)) == NULL)
4494 return REG_BANK(reg);
4499 /*-----------------------------------------------------------------*/
4500 /*-----------------------------------------------------------------*/
4501 void FixRegisterBanking(pBlock *pb)
4512 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4513 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4516 /* loop through all of the flow blocks with in one pblock */
4518 //fprintf(stderr,"Register banking\n");
4521 /* at this point, pc should point to a PC_FLOW object */
4524 /* for each flow block, determine the register banking
4529 //genericPrint(stderr, pc);
4531 reg = getRegFromInstruction(pc);
4534 fprintf(stderr, " %s ",reg->name);
4535 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4536 reg->address,REG_BANK(reg),reg->isBitField);
4540 if(reg && REG_BANK(reg)!=cur_bank) {
4541 //fprintf(stderr,"need to switch banks\n");
4542 /* Examine the instruction before this one to make sure it is
4543 * not a skip type instruction */
4544 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4545 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4546 int b = cur_bank ^ REG_BANK(reg);
4548 cur_bank = REG_BANK(reg);
4554 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4557 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4558 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4562 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4563 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4565 insertBankSwitch(0, pc, -1, -1);
4572 //fprintf(stderr, "Bummer can't switch banks\n");
4582 // } while(pc && !(isPCFL(pc)));
4587 if(pcprev && cur_bank) {
4589 int pos = 1; /* Assume that the bank swithc instruction(s)
4590 * are inserted after this instruction */
4592 if((PCI(pcprev)->op == POC_RETLW) ||
4593 (PCI(pcprev)->op == POC_RETURN) ||
4594 (PCI(pcprev)->op == POC_RETFIE)) {
4596 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4602 /* Brute force - make sure that we point to bank 0 at the
4603 * end of each flow block */
4605 switch(cur_bank & 3) {
4609 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4612 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4613 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4616 insertBankSwitch(pos, pcprev, -1, -1);
4621 new_pc = newpCode(POC_BCF,
4622 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4623 pCodeInsertAfter(pcprev, new_pc);
4626 //fprintf(stderr, "Brute force switch\n");
4631 void pBlockDestruct(pBlock *pb)
4642 /*-----------------------------------------------------------------*/
4643 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4644 /* name dbName and combine them */
4645 /* into one block */
4646 /*-----------------------------------------------------------------*/
4647 void mergepBlocks(char dbName)
4650 pBlock *pb, *pbmerged = NULL,*pbn;
4652 pb = the_pFile->pbHead;
4654 //fprintf(stderr," merging blocks named %c\n",dbName);
4658 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4659 if( getpBlock_dbName(pb) == dbName) {
4661 //fprintf(stderr," merged block %c\n",dbName);
4666 addpCode2pBlock(pbmerged, pb->pcHead);
4667 /* addpCode2pBlock doesn't handle the tail: */
4668 pbmerged->pcTail = pb->pcTail;
4670 pb->prev->next = pbn;
4672 pbn->prev = pb->prev;
4677 //printpBlock(stderr, pbmerged);
4684 /*-----------------------------------------------------------------*/
4685 /* AnalyzeFlow - Examine the flow of the code and optimize */
4687 /* level 0 == minimal optimization */
4688 /* optimize registers that are used only by two instructions */
4689 /* level 1 == maximal optimization */
4690 /* optimize by looking at pairs of instructions that use the */
4692 /*-----------------------------------------------------------------*/
4694 void AnalyzeFlow(int level)
4696 static int times_called=0;
4704 /* if this is not the first time this function has been called,
4705 then clean up old flow information */
4706 if(times_called++) {
4707 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4710 RegsUnMapLiveRanges();
4716 /* Phase 2 - Flow Analysis - Register Banking
4718 * In this phase, the individual flow blocks are examined
4719 * and register banking is fixed.
4722 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4723 //FixRegisterBanking(pb);
4725 /* Phase 2 - Flow Analysis
4727 * In this phase, the pCode is partition into pCodeFlow
4728 * blocks. The flow blocks mark the points where a continuous
4729 * stream of instructions changes flow (e.g. because of
4730 * a call or goto or whatever).
4733 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4737 /* Phase 2 - Flow Analysis - linking flow blocks
4739 * In this phase, the individual flow blocks are examined
4740 * to determine their order of excution.
4743 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4746 /* Phase 3 - Flow Analysis - Flow Tree
4748 * In this phase, the individual flow blocks are examined
4749 * to determine their order of excution.
4752 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4756 /* Phase x - Flow Analysis - Used Banks
4758 * In this phase, the individual flow blocks are examined
4759 * to determine the Register Banks they use
4762 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4766 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4767 pCodeRegMapLiveRanges(pb);
4769 RemoveUnusedRegisters();
4771 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4772 pCodeRegOptimizeRegUsage(level);
4778 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4782 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4784 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4785 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4786 pcflow = pcflow->next) {
4788 FillFlow(PCFL(pcflow));
4793 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4795 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4796 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4797 pcflow = pcflow->next) {
4799 FlowStats(PCFL(pcflow));
4805 /*-----------------------------------------------------------------*/
4806 /* AnalyzeBanking - Called after the memory addresses have been */
4807 /* assigned to the registers. */
4809 /*-----------------------------------------------------------------*/
4811 void AnalyzeBanking(void)
4815 if(!picIsInitialized()) {
4816 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4817 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4818 fprintf(stderr,"support/scripts/inc2h.pl\n");
4819 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4824 /* Phase x - Flow Analysis - Used Banks
4826 * In this phase, the individual flow blocks are examined
4827 * to determine the Register Banks they use
4833 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4835 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4836 FixRegisterBanking(pb);
4840 /*-----------------------------------------------------------------*/
4841 /* buildCallTree - look at the flow and extract all of the calls */
4843 /*-----------------------------------------------------------------*/
4844 set *register_usage(pBlock *pb);
4846 void buildCallTree(void )
4857 /* Now build the call tree.
4858 First we examine all of the pCodes for functions.
4859 Keep in mind that the function boundaries coincide
4860 with pBlock boundaries.
4862 The algorithm goes something like this:
4863 We have two nested loops. The outer loop iterates
4864 through all of the pBlocks/functions. The inner
4865 loop iterates through all of the pCodes for
4866 a given pBlock. When we begin iterating through
4867 a pBlock, the variable pc_fstart, pCode of the start
4868 of a function, is cleared. We then search for pCodes
4869 of type PC_FUNCTION. When one is encountered, we
4870 initialize pc_fstart to this and at the same time
4871 associate a new pBranch object that signifies a
4872 branch entry. If a return is found, then this signifies
4873 a function exit point. We'll link the pCodes of these
4874 returns to the matching pc_fstart.
4876 When we're done, a doubly linked list of pBranches
4877 will exist. The head of this list is stored in
4878 `the_pFile', which is the meta structure for all
4879 of the pCode. Look at the printCallTree function
4880 on how the pBranches are linked together.
4883 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4884 pCode *pc_fstart=NULL;
4885 for(pc = pb->pcHead; pc; pc = pc->next) {
4887 if (PCF(pc)->fname) {
4889 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4890 //fprintf(stderr," found main \n");
4891 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4895 pbr = Safe_calloc(1,sizeof(pBranch));
4896 pbr->pc = pc_fstart = pc;
4899 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4901 // Here's a better way of doing the same:
4902 addSet(&pb->function_entries, pc);
4905 // Found an exit point in a function, e.g. return
4906 // (Note, there may be more than one return per function)
4908 pBranchLink(PCF(pc_fstart), PCF(pc));
4910 addSet(&pb->function_exits, pc);
4912 } else if(isCALL(pc)) {
4913 addSet(&pb->function_calls,pc);
4918 /* Re-allocate the registers so that there are no collisions
4919 * between local variables when one function call another */
4922 // pic14_deallocateAllRegs();
4924 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4931 /*-----------------------------------------------------------------*/
4932 /* AnalyzepCode - parse the pCode that has been generated and form */
4933 /* all of the logical connections. */
4935 /* Essentially what's done here is that the pCode flow is */
4937 /*-----------------------------------------------------------------*/
4939 void AnalyzepCode(char dbName)
4950 /* Phase 1 - Register allocation and peep hole optimization
4952 * The first part of the analysis is to determine the registers
4953 * that are used in the pCode. Once that is done, the peep rules
4954 * are applied to the code. We continue to loop until no more
4955 * peep rule optimizations are found (or until we exceed the
4956 * MAX_PASSES threshold).
4958 * When done, the required registers will be determined.
4964 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4965 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4967 /* First, merge the labels with the instructions */
4968 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4969 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4971 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4972 //fprintf(stderr," analyze and merging block %c\n",dbName);
4973 pBlockMergeLabels(pb);
4976 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4980 changes = OptimizepCode(dbName);
4982 } while(changes && (i++ < MAX_PASSES));
4987 /*-----------------------------------------------------------------*/
4988 /* ispCodeFunction - returns true if *pc is the pCode of a */
4990 /*-----------------------------------------------------------------*/
4991 bool ispCodeFunction(pCode *pc)
4994 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5000 /*-----------------------------------------------------------------*/
5001 /* findFunction - Search for a function by name (given the name) */
5002 /* in the set of all functions that are in a pBlock */
5003 /* (note - I expect this to change because I'm planning to limit */
5004 /* pBlock's to just one function declaration */
5005 /*-----------------------------------------------------------------*/
5006 pCode *findFunction(char *fname)
5013 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5015 pc = setFirstItem(pb->function_entries);
5018 if((pc->type == PC_FUNCTION) &&
5020 (strcmp(fname, PCF(pc)->fname)==0))
5023 pc = setNextItem(pb->function_entries);
5031 void MarkUsedRegisters(set *regset)
5036 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5037 r2 = pic14_regWithIdx(r1->rIdx);
5043 void pBlockStats(FILE *of, pBlock *pb)
5049 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5051 // for now just print the first element of each set
5052 pc = setFirstItem(pb->function_entries);
5054 fprintf(of,";entry: ");
5057 pc = setFirstItem(pb->function_exits);
5059 fprintf(of,";has an exit\n");
5063 pc = setFirstItem(pb->function_calls);
5065 fprintf(of,";functions called:\n");
5068 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5069 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5071 pc = setNextItem(pb->function_calls);
5075 r = setFirstItem(pb->tregisters);
5077 int n = elementsInSet(pb->tregisters);
5079 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5082 fprintf(of,"; %s\n",r->name);
5083 r = setNextItem(pb->tregisters);
5088 /*-----------------------------------------------------------------*/
5089 /*-----------------------------------------------------------------*/
5091 static void sequencepCode(void)
5097 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5099 pb->seq = GpCodeSequenceNumber+1;
5101 for( pc = pb->pcHead; pc; pc = pc->next)
5102 pc->seq = ++GpCodeSequenceNumber;
5108 /*-----------------------------------------------------------------*/
5109 /*-----------------------------------------------------------------*/
5110 set *register_usage(pBlock *pb)
5113 set *registers=NULL;
5114 set *registersInCallPath = NULL;
5116 /* check recursion */
5118 pc = setFirstItem(pb->function_entries);
5125 if(pc->type != PC_FUNCTION)
5126 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5128 pc = setFirstItem(pb->function_calls);
5129 for( ; pc; pc = setNextItem(pb->function_calls)) {
5131 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5132 char *dest = get_op_from_instruction(PCI(pc));
5134 pcn = findFunction(dest);
5136 registersInCallPath = register_usage(pcn->pb);
5138 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5143 pBlockStats(stderr,pb); // debug
5146 // Mark the registers in this block as used.
5148 MarkUsedRegisters(pb->tregisters);
5149 if(registersInCallPath) {
5150 /* registers were used in the functions this pBlock has called */
5151 /* so now, we need to see if these collide with the ones we are */
5154 regs *r1,*r2, *newreg;
5156 DFPRINTF((stderr,"comparing registers\n"));
5158 r1 = setFirstItem(registersInCallPath);
5161 r2 = setFirstItem(pb->tregisters);
5163 while(r2 && (r1->type != REG_STK)) {
5165 if(r2->rIdx == r1->rIdx) {
5166 newreg = pic14_findFreeReg(REG_GPR);
5170 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5174 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5175 r1->rIdx, newreg->rIdx));
5176 r2->rIdx = newreg->rIdx;
5177 //if(r2->name) free(r2->name);
5179 r2->name = Safe_strdup(newreg->name);
5183 newreg->wasUsed = 1;
5185 r2 = setNextItem(pb->tregisters);
5188 r1 = setNextItem(registersInCallPath);
5191 /* Collisions have been resolved. Now free the registers in the call path */
5192 r1 = setFirstItem(registersInCallPath);
5194 if(r1->type != REG_STK) {
5195 newreg = pic14_regWithIdx(r1->rIdx);
5198 r1 = setNextItem(registersInCallPath);
5202 // MarkUsedRegisters(pb->registers);
5204 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5207 DFPRINTF((stderr,"returning regs\n"));
5209 DFPRINTF((stderr,"not returning regs\n"));
5211 DFPRINTF((stderr,"pBlock after register optim.\n"));
5212 pBlockStats(stderr,pb); // debug
5218 /*-----------------------------------------------------------------*/
5219 /* printCallTree - writes the call tree to a file */
5221 /*-----------------------------------------------------------------*/
5222 void pct2(FILE *of,pBlock *pb,int indent)
5226 // set *registersInCallPath = NULL;
5232 return; //recursion ?
5234 pc = setFirstItem(pb->function_entries);
5241 for(i=0;i<indent;i++) // Indentation
5244 if(pc->type == PC_FUNCTION)
5245 fprintf(of,"%s\n",PCF(pc)->fname);
5250 pc = setFirstItem(pb->function_calls);
5251 for( ; pc; pc = setNextItem(pb->function_calls)) {
5253 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5254 char *dest = get_op_from_instruction(PCI(pc));
5256 pcn = findFunction(dest);
5258 pct2(of,pcn->pb,indent+1);
5260 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5268 /*-----------------------------------------------------------------*/
5269 /* printCallTree - writes the call tree to a file */
5271 /*-----------------------------------------------------------------*/
5273 void printCallTree(FILE *of)
5285 fprintf(of, "\npBlock statistics\n");
5286 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5291 fprintf(of,"Call Tree\n");
5292 pbr = the_pFile->functions;
5296 if(!ispCodeFunction(pc))
5297 fprintf(of,"bug in call tree");
5300 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5302 while(pc->next && !ispCodeFunction(pc->next)) {
5304 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5305 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5313 fprintf(of,"\n**************\n\na better call tree\n");
5314 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5319 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5320 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5326 /*-----------------------------------------------------------------*/
5328 /*-----------------------------------------------------------------*/
5330 void InlineFunction(pBlock *pb)
5338 pc = setFirstItem(pb->function_calls);
5340 for( ; pc; pc = setNextItem(pb->function_calls)) {
5343 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5349 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5351 //fprintf(stderr,"Cool can inline:\n");
5352 //pcn->print(stderr,pcn);
5354 //fprintf(stderr,"recursive call Inline\n");
5355 InlineFunction(pcn->pb);
5356 //fprintf(stderr,"return from recursive call Inline\n");
5359 At this point, *pc points to a CALL mnemonic, and
5360 *pcn points to the function that is being called.
5362 To in-line this call, we need to remove the CALL
5363 and RETURN(s), and link the function pCode in with
5369 /* Remove the CALL */
5373 /* remove callee pBlock from the pBlock linked list */
5374 removepBlock(pcn->pb);
5382 /* Remove the Function pCode */
5383 pct = findNextInstruction(pcn->next);
5385 /* Link the function with the callee */
5386 pc->next = pcn->next;
5387 pcn->next->prev = pc;
5389 /* Convert the function name into a label */
5391 pbr = Safe_calloc(1,sizeof(pBranch));
5392 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5394 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5395 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5397 /* turn all of the return's except the last into goto's */
5398 /* check case for 2 instruction pBlocks */
5399 pce = findNextInstruction(pcn->next);
5401 pCode *pce_next = findNextInstruction(pce->next);
5403 if(pce_next == NULL) {
5404 /* found the last return */
5405 pCode *pc_call_next = findNextInstruction(pc_call->next);
5407 //fprintf(stderr,"found last return\n");
5408 //pce->print(stderr,pce);
5409 pce->prev->next = pc_call->next;
5410 pc_call->next->prev = pce->prev;
5411 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5421 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5427 /*-----------------------------------------------------------------*/
5429 /*-----------------------------------------------------------------*/
5431 void InlinepCode(void)
5440 if(!functionInlining)
5443 /* Loop through all of the function definitions and count the
5444 * number of times each one is called */
5445 //fprintf(stderr,"inlining %d\n",__LINE__);
5447 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5449 pc = setFirstItem(pb->function_calls);
5451 for( ; pc; pc = setNextItem(pb->function_calls)) {
5454 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5455 if(pcn && isPCF(pcn)) {
5456 PCF(pcn)->ncalled++;
5459 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5464 //fprintf(stderr,"inlining %d\n",__LINE__);
5466 /* Now, Loop through the function definitions again, but this
5467 * time inline those functions that have only been called once. */
5469 InlineFunction(the_pFile->pbHead);
5470 //fprintf(stderr,"inlining %d\n",__LINE__);
5472 for(pb = the_pFile->pbHead; pb; pb = pb->next)