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 */
79 static int GpCodeSequenceNumber = 1;
82 extern void RemoveUnusedRegisters(void);
83 extern void BuildFlowTree(pBlock *pb);
84 extern void pCodeRegOptimizeRegUsage(void);
86 /****************************************************************/
87 /* Forward declarations */
88 /****************************************************************/
90 void unlinkpCode(pCode *pc);
92 static void genericAnalyze(pCode *pc);
93 static void AnalyzeGOTO(pCode *pc);
94 static void AnalyzeSKIP(pCode *pc);
95 static void AnalyzeRETURN(pCode *pc);
98 static void genericDestruct(pCode *pc);
99 static void genericPrint(FILE *of,pCode *pc);
101 static void pCodePrintLabel(FILE *of, pCode *pc);
102 static void pCodePrintFunction(FILE *of, pCode *pc);
103 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
104 static char *get_op_from_instruction( pCodeInstruction *pcc);
105 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
106 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
107 int pCodePeepMatchRule(pCode *pc);
108 void pBlockStats(FILE *of, pBlock *pb);
109 pBlock *newpBlock(void);
110 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
111 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
112 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
113 void pCodeRegMapLiveRanges(pBlock *pb);
116 /****************************************************************/
117 /* PIC Instructions */
118 /****************************************************************/
120 pCodeInstruction pciADDWF = {
121 {PC_OPCODE, NULL, NULL, 0, NULL,
134 1,0, // dest, bit instruction
137 (PCC_W | PCC_REGISTER), // inCond
138 (PCC_REGISTER | PCC_Z) // outCond
141 pCodeInstruction pciADDFW = {
142 {PC_OPCODE, NULL, NULL, 0, NULL,
155 0,0, // dest, bit instruction
158 (PCC_W | PCC_REGISTER), // inCond
159 (PCC_W | PCC_Z) // outCond
162 pCodeInstruction pciADDLW = {
163 {PC_OPCODE, NULL, NULL, 0, NULL,
176 0,0, // dest, bit instruction
179 (PCC_W | PCC_LITERAL), // inCond
180 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
183 pCodeInstruction pciANDLW = {
184 {PC_OPCODE, NULL, NULL, 0, NULL,
197 0,0, // dest, bit instruction
200 (PCC_W | PCC_LITERAL), // inCond
201 (PCC_W | PCC_Z) // outCond
204 pCodeInstruction pciANDWF = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 1,0, // dest, bit instruction
221 (PCC_W | PCC_REGISTER), // inCond
222 (PCC_REGISTER | PCC_Z) // outCond
225 pCodeInstruction pciANDFW = {
226 {PC_OPCODE, NULL, NULL, 0, NULL,
239 0,0, // dest, bit instruction
242 (PCC_W | PCC_REGISTER), // inCond
243 (PCC_W | PCC_Z) // outCond
246 pCodeInstruction pciBCF = {
247 {PC_OPCODE, NULL, NULL, 0, NULL,
260 1,1, // dest, bit instruction
263 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
264 PCC_REGISTER // outCond
267 pCodeInstruction pciBSF = {
268 {PC_OPCODE, NULL, NULL, 0, NULL,
281 1,1, // dest, bit instruction
284 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
285 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
288 pCodeInstruction pciBTFSC = {
289 {PC_OPCODE, NULL, NULL, 0, NULL,
302 0,1, // dest, bit instruction
305 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
306 PCC_EXAMINE_PCOP // outCond
309 pCodeInstruction pciBTFSS = {
310 {PC_OPCODE, NULL, NULL, 0, NULL,
323 0,1, // dest, bit instruction
326 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
327 PCC_EXAMINE_PCOP // outCond
330 pCodeInstruction pciCALL = {
331 {PC_OPCODE, NULL, NULL, 0, NULL,
344 0,0, // dest, bit instruction
351 pCodeInstruction pciCOMF = {
352 {PC_OPCODE, NULL, NULL, 0, NULL,
365 1,0, // dest, bit instruction
368 PCC_REGISTER, // inCond
369 PCC_REGISTER // outCond
372 pCodeInstruction pciCOMFW = {
373 {PC_OPCODE, NULL, NULL, 0, NULL,
386 0,0, // dest, bit instruction
389 PCC_REGISTER, // inCond
393 pCodeInstruction pciCLRF = {
394 {PC_OPCODE, NULL, NULL, 0, NULL,
407 0,0, // dest, bit instruction
411 PCC_REGISTER // outCond
414 pCodeInstruction pciCLRW = {
415 {PC_OPCODE, NULL, NULL, 0, NULL,
428 0,0, // dest, bit instruction
435 pCodeInstruction pciDECF = {
436 {PC_OPCODE, NULL, NULL, 0, NULL,
449 1,0, // dest, bit instruction
452 PCC_REGISTER, // inCond
453 PCC_REGISTER // outCond
456 pCodeInstruction pciDECFW = {
457 {PC_OPCODE, NULL, NULL, 0, NULL,
470 0,0, // dest, bit instruction
473 PCC_REGISTER, // inCond
477 pCodeInstruction pciDECFSZ = {
478 {PC_OPCODE, NULL, NULL, 0, NULL,
491 1,0, // dest, bit instruction
494 PCC_REGISTER, // inCond
495 PCC_REGISTER // outCond
498 pCodeInstruction pciDECFSZW = {
499 {PC_OPCODE, NULL, NULL, 0, NULL,
512 0,0, // dest, bit instruction
515 PCC_REGISTER, // inCond
519 pCodeInstruction pciGOTO = {
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 0,0, // dest, bit instruction
540 pCodeInstruction pciINCF = {
541 {PC_OPCODE, NULL, NULL, 0, NULL,
554 1,0, // dest, bit instruction
557 PCC_REGISTER, // inCond
558 PCC_REGISTER // outCond
561 pCodeInstruction pciINCFW = {
562 {PC_OPCODE, NULL, NULL, 0, NULL,
575 0,0, // dest, bit instruction
578 PCC_REGISTER, // inCond
582 pCodeInstruction pciINCFSZ = {
583 {PC_OPCODE, NULL, NULL, 0, NULL,
596 1,0, // dest, bit instruction
599 PCC_REGISTER, // inCond
600 PCC_REGISTER // outCond
603 pCodeInstruction pciINCFSZW = {
604 {PC_OPCODE, NULL, NULL, 0, NULL,
617 0,0, // dest, bit instruction
620 PCC_REGISTER, // inCond
624 pCodeInstruction pciIORWF = {
625 {PC_OPCODE, NULL, NULL, 0, NULL,
638 1,0, // dest, bit instruction
641 (PCC_W | PCC_REGISTER), // inCond
642 (PCC_REGISTER | PCC_Z) // outCond
645 pCodeInstruction pciIORFW = {
646 {PC_OPCODE, NULL, NULL, 0, NULL,
659 0,0, // dest, bit instruction
662 (PCC_W | PCC_REGISTER), // inCond
663 (PCC_W | PCC_Z) // outCond
666 pCodeInstruction pciIORLW = {
667 {PC_OPCODE, NULL, NULL, 0, NULL,
680 0,0, // dest, bit instruction
683 (PCC_W | PCC_LITERAL), // inCond
684 (PCC_W | PCC_Z) // outCond
687 pCodeInstruction pciMOVF = {
688 {PC_OPCODE, NULL, NULL, 0, NULL,
701 1,0, // dest, bit instruction
704 PCC_REGISTER, // inCond
708 pCodeInstruction pciMOVFW = {
709 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,0, // dest, bit instruction
725 PCC_REGISTER, // inCond
726 (PCC_W | PCC_Z) // outCond
729 pCodeInstruction pciMOVWF = {
730 {PC_OPCODE, NULL, NULL, 0, NULL,
743 0,0, // dest, bit instruction
747 PCC_REGISTER // outCond
750 pCodeInstruction pciMOVLW = {
751 {PC_OPCODE, NULL, NULL, 0, NULL,
764 0,0, // dest, bit instruction
767 (PCC_NONE | PCC_LITERAL), // inCond
771 pCodeInstruction pciNOP = {
772 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
791 pCodeInstruction pciRETFIE = {
792 {PC_OPCODE, NULL, NULL, 0, NULL,
805 0,0, // dest, bit instruction
809 PCC_NONE // outCond (not true... affects the GIE bit too)
812 pCodeInstruction pciRETLW = {
813 {PC_OPCODE, NULL, NULL, 0, NULL,
826 0,0, // dest, bit instruction
829 PCC_LITERAL, // inCond
833 pCodeInstruction pciRETURN = {
834 {PC_OPCODE, NULL, NULL, 0, NULL,
847 0,0, // dest, bit instruction
854 pCodeInstruction pciRLF = {
855 {PC_OPCODE, NULL, NULL, 0, NULL,
868 1,0, // dest, bit instruction
871 (PCC_C | PCC_REGISTER), // inCond
872 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
875 pCodeInstruction pciRLFW = {
876 {PC_OPCODE, NULL, NULL, 0, NULL,
889 0,0, // dest, bit instruction
892 (PCC_C | PCC_REGISTER), // inCond
893 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
896 pCodeInstruction pciRRF = {
897 {PC_OPCODE, NULL, NULL, 0, NULL,
910 1,0, // dest, bit instruction
913 (PCC_C | PCC_REGISTER), // inCond
914 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
917 pCodeInstruction pciRRFW = {
918 {PC_OPCODE, NULL, NULL, 0, NULL,
931 0,0, // dest, bit instruction
934 (PCC_C | PCC_REGISTER), // inCond
935 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
938 pCodeInstruction pciSUBWF = {
939 {PC_OPCODE, NULL, NULL, 0, NULL,
952 1,0, // dest, bit instruction
955 (PCC_W | PCC_REGISTER), // inCond
956 (PCC_REGISTER | PCC_Z) // outCond
959 pCodeInstruction pciSUBFW = {
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 0,0, // dest, bit instruction
976 (PCC_W | PCC_REGISTER), // inCond
977 (PCC_W | PCC_Z) // outCond
980 pCodeInstruction pciSUBLW = {
981 {PC_OPCODE, NULL, NULL, 0, NULL,
994 0,0, // dest, bit instruction
997 (PCC_W | PCC_LITERAL), // inCond
998 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1001 pCodeInstruction pciSWAPF = {
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1008 NULL, // from branch
1015 1,0, // dest, bit instruction
1016 0,0, // branch, skip
1018 (PCC_REGISTER), // inCond
1019 (PCC_REGISTER) // outCond
1022 pCodeInstruction pciSWAPFW = {
1023 {PC_OPCODE, NULL, NULL, 0, NULL,
1029 NULL, // from branch
1036 0,0, // dest, bit instruction
1037 0,0, // branch, skip
1039 (PCC_REGISTER), // inCond
1043 pCodeInstruction pciTRIS = {
1044 {PC_OPCODE, NULL, NULL, 0, NULL,
1050 NULL, // from branch
1057 0,0, // dest, bit instruction
1058 0,0, // branch, skip
1061 PCC_REGISTER // outCond
1064 pCodeInstruction pciXORWF = {
1065 {PC_OPCODE, NULL, NULL, 0, NULL,
1071 NULL, // from branch
1078 1,0, // dest, bit instruction
1079 0,0, // branch, skip
1081 (PCC_W | PCC_REGISTER), // inCond
1082 (PCC_REGISTER | PCC_Z) // outCond
1085 pCodeInstruction pciXORFW = {
1086 {PC_OPCODE, NULL, NULL, 0, NULL,
1092 NULL, // from branch
1099 0,0, // dest, bit instruction
1100 0,0, // branch, skip
1102 (PCC_W | PCC_REGISTER), // inCond
1103 (PCC_W | PCC_Z) // outCond
1106 pCodeInstruction pciXORLW = {
1107 {PC_OPCODE, NULL, NULL, 0, NULL,
1113 NULL, // from branch
1120 0,0, // dest, bit instruction
1121 0,0, // branch, skip
1123 (PCC_W | PCC_LITERAL), // inCond
1124 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1128 #define MAX_PIC14MNEMONICS 100
1129 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1131 /* This definition needs to be part of configure.in */
1132 // #define USE_VSNPRINTF
1134 #ifdef USE_VSNPRINTF
1135 // Alas, vsnprintf is not ANSI standard, and does not exist
1136 // on Solaris (and probably other non-Gnu flavored Unixes).
1138 /*-----------------------------------------------------------------*/
1139 /* SAFE_snprintf - like snprintf except the string pointer is */
1140 /* after the string has been printed to. This is */
1141 /* useful for printing to string as though if it */
1142 /* were a stream. */
1143 /*-----------------------------------------------------------------*/
1144 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1152 va_start(val, format);
1154 vsnprintf(*str, *size, format, val);
1160 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1161 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1169 #else // USE_VSNPRINTF
1171 // This version is *not* safe, despite the name.
1173 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1177 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1182 va_start(val, format);
1184 vsprintf(buffer, format, val);
1187 len = strlen(buffer);
1189 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1190 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1193 strcpy(*str, buffer);
1199 #endif // USE_VSNPRINTF
1202 extern void initStack(int base_address, int size);
1203 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1204 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1205 extern void init_pic(char *);
1207 void pCodeInitRegisters(void)
1210 initStack(0xfff, 8);
1211 init_pic(port->processor);
1213 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1214 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1215 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1216 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1217 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1218 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1220 pc_status.rIdx = IDX_STATUS;
1221 pc_fsr.rIdx = IDX_FSR;
1222 pc_indf.rIdx = IDX_INDF;
1223 pc_intcon.rIdx = IDX_INTCON;
1224 pc_pcl.rIdx = IDX_PCL;
1225 pc_pclath.rIdx = IDX_PCLATH;
1227 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1228 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1229 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1231 pc_kzero.rIdx = IDX_KZ;
1232 pc_wsave.rIdx = IDX_WSAVE;
1233 pc_ssave.rIdx = IDX_SSAVE;
1235 /* probably should put this in a separate initialization routine */
1236 pb_dead_pcodes = newpBlock();
1240 /*-----------------------------------------------------------------*/
1241 /* mnem2key - convert a pic mnemonic into a hash key */
1242 /* (BTW - this spreads the mnemonics quite well) */
1244 /*-----------------------------------------------------------------*/
1246 int mnem2key(char const *mnem)
1255 key += toupper(*mnem++) +1;
1259 return (key & 0x1f);
1263 void pic14initMnemonics(void)
1268 pCodeInstruction *pci;
1270 if(mnemonics_initialized)
1273 //FIXME - probably should NULL out the array before making the assignments
1274 //since we check the array contents below this initialization.
1276 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1277 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1278 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1279 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1280 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1281 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1282 pic14Mnemonics[POC_BCF] = &pciBCF;
1283 pic14Mnemonics[POC_BSF] = &pciBSF;
1284 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1285 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1286 pic14Mnemonics[POC_CALL] = &pciCALL;
1287 pic14Mnemonics[POC_COMF] = &pciCOMF;
1288 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1289 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1290 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1291 pic14Mnemonics[POC_DECF] = &pciDECF;
1292 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1293 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1294 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1295 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1296 pic14Mnemonics[POC_INCF] = &pciINCF;
1297 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1298 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1299 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1300 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1301 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1302 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1303 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1304 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1305 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1306 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1307 pic14Mnemonics[POC_NOP] = &pciNOP;
1308 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1309 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1310 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1311 pic14Mnemonics[POC_RLF] = &pciRLF;
1312 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1313 pic14Mnemonics[POC_RRF] = &pciRRF;
1314 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1315 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1316 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1317 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1318 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1319 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1320 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1321 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1322 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1323 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1325 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1326 if(pic14Mnemonics[i])
1327 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1328 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1331 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1332 pci = hTabNextItem(pic14MnemonicsHash, &key);
1335 mnemonics_initialized = 1;
1338 int getpCodePeepCommand(char *cmd);
1340 int getpCode(char *mnem,unsigned dest)
1343 pCodeInstruction *pci;
1344 int key = mnem2key(mnem);
1346 if(!mnemonics_initialized)
1347 pic14initMnemonics();
1349 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1353 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1354 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1358 pci = hTabNextItemWK (pic14MnemonicsHash);
1365 /*-----------------------------------------------------------------*
1366 * pic14initpCodePeepCommands
1368 *-----------------------------------------------------------------*/
1369 void pic14initpCodePeepCommands(void)
1377 hTabAddItem(&pic14pCodePeepCommandsHash,
1378 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1380 } while (peepCommands[i].cmd);
1382 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1385 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1386 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1391 /*-----------------------------------------------------------------
1394 *-----------------------------------------------------------------*/
1396 int getpCodePeepCommand(char *cmd)
1400 int key = mnem2key(cmd);
1403 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1406 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1407 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1411 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1418 char getpBlock_dbName(pBlock *pb)
1424 return pb->cmemmap->dbName;
1428 void pBlockConvert2ISR(pBlock *pb)
1439 /*-----------------------------------------------------------------*/
1440 /* movepBlock2Head - given the dbname of a pBlock, move all */
1441 /* instances to the front of the doubly linked */
1442 /* list of pBlocks */
1443 /*-----------------------------------------------------------------*/
1445 void movepBlock2Head(char dbName)
1449 pb = the_pFile->pbHead;
1453 if(getpBlock_dbName(pb) == dbName) {
1454 pBlock *pbn = pb->next;
1455 pb->next = the_pFile->pbHead;
1456 the_pFile->pbHead->prev = pb;
1457 the_pFile->pbHead = pb;
1460 pb->prev->next = pbn;
1462 // If the pBlock that we just moved was the last
1463 // one in the link of all of the pBlocks, then we
1464 // need to point the tail to the block just before
1465 // the one we moved.
1466 // Note: if pb->next is NULL, then pb must have
1467 // been the last pBlock in the chain.
1470 pbn->prev = pb->prev;
1472 the_pFile->pbTail = pb->prev;
1483 void copypCode(FILE *of, char dbName)
1487 if(!of || !the_pFile)
1490 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1491 if(getpBlock_dbName(pb) == dbName) {
1498 void pcode_test(void)
1501 DFPRINTF((stderr,"pcode is alive!\n"));
1511 /* create the file name */
1512 strcpy(buffer,srcFileName);
1513 strcat(buffer,".p");
1515 if( !(pFile = fopen(buffer, "w" ))) {
1516 werror(E_FILE_OPEN_ERR,buffer);
1520 fprintf(pFile,"pcode dump\n\n");
1522 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1523 fprintf(pFile,"\n\tNew pBlock\n\n");
1525 fprintf(pFile,"%s",pb->cmemmap->sname);
1527 fprintf(pFile,"internal pblock");
1529 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1530 printpBlock(pFile,pb);
1534 /*-----------------------------------------------------------------*/
1535 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1536 /* ister, RegCond will return the bit being referenced. */
1538 /* fixme - why not just OR in the pcop bit field */
1539 /*-----------------------------------------------------------------*/
1541 static int RegCond(pCodeOp *pcop)
1547 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1548 switch(PCORB(pcop)->bit) {
1562 /*-----------------------------------------------------------------*/
1563 /* newpCode - create and return a newly initialized pCode */
1565 /* fixme - rename this */
1567 /* The purpose of this routine is to create a new Instruction */
1568 /* pCode. This is called by gen.c while the assembly code is being */
1572 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1573 /* (note that the op is analogous to but not the */
1574 /* same thing as the opcode of the instruction.) */
1575 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1578 /* a pointer to the new malloc'd pCode is returned. */
1582 /*-----------------------------------------------------------------*/
1583 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1585 pCodeInstruction *pci ;
1587 if(!mnemonics_initialized)
1588 pic14initMnemonics();
1590 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1592 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1593 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1596 if(pci->inCond & PCC_EXAMINE_PCOP)
1597 pci->inCond |= RegCond(pcop);
1599 if(pci->outCond & PCC_EXAMINE_PCOP)
1600 pci->outCond |= RegCond(pcop);
1602 pci->pc.prev = pci->pc.next = NULL;
1603 return (pCode *)pci;
1606 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1612 /*-----------------------------------------------------------------*/
1613 /* newpCodeWild - create a "wild" as in wild card pCode */
1615 /* Wild pcodes are used during the peep hole optimizer to serve */
1616 /* as place holders for any instruction. When a snippet of code is */
1617 /* compared to a peep hole rule, the wild card opcode will match */
1618 /* any instruction. However, the optional operand and label are */
1619 /* additional qualifiers that must also be matched before the */
1620 /* line (of assembly code) is declared matched. Note that the */
1621 /* operand may be wild too. */
1623 /* Note, a wild instruction is specified just like a wild var: */
1624 /* %4 ; A wild instruction, */
1625 /* See the peeph.def file for additional examples */
1627 /*-----------------------------------------------------------------*/
1629 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1634 pcw = Safe_calloc(1,sizeof(pCodeWild));
1636 pcw->pci.pc.type = PC_WILD;
1637 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1638 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1639 pcw->pci.pc.pb = NULL;
1641 // pcw->pci.pc.analyze = genericAnalyze;
1642 pcw->pci.pc.destruct = genericDestruct;
1643 pcw->pci.pc.print = genericPrint;
1645 pcw->id = pCodeID; // this is the 'n' in %n
1646 pcw->operand = optional_operand;
1647 pcw->label = optional_label;
1649 pcw->mustBeBitSkipInst = 0;
1650 pcw->mustNotBeBitSkipInst = 0;
1651 pcw->invertBitSkipInst = 0;
1653 return ( (pCode *)pcw);
1657 /*-----------------------------------------------------------------*/
1658 /* newPcodeInlineP - create a new pCode from a char string */
1659 /*-----------------------------------------------------------------*/
1662 pCode *newpCodeInlineP(char *cP)
1667 pcc = Safe_calloc(1,sizeof(pCodeComment));
1669 pcc->pc.type = PC_INLINE;
1670 pcc->pc.prev = pcc->pc.next = NULL;
1671 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1674 // pcc->pc.analyze = genericAnalyze;
1675 pcc->pc.destruct = genericDestruct;
1676 pcc->pc.print = genericPrint;
1679 pcc->comment = Safe_strdup(cP);
1681 pcc->comment = NULL;
1683 return ( (pCode *)pcc);
1687 /*-----------------------------------------------------------------*/
1688 /* newPcodeCharP - create a new pCode from a char string */
1689 /*-----------------------------------------------------------------*/
1691 pCode *newpCodeCharP(char *cP)
1696 pcc = Safe_calloc(1,sizeof(pCodeComment));
1698 pcc->pc.type = PC_COMMENT;
1699 pcc->pc.prev = pcc->pc.next = NULL;
1700 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1703 // pcc->pc.analyze = genericAnalyze;
1704 pcc->pc.destruct = genericDestruct;
1705 pcc->pc.print = genericPrint;
1708 pcc->comment = Safe_strdup(cP);
1710 pcc->comment = NULL;
1712 return ( (pCode *)pcc);
1716 /*-----------------------------------------------------------------*/
1717 /* newpCodeFunction - */
1718 /*-----------------------------------------------------------------*/
1721 pCode *newpCodeFunction(char *mod,char *f)
1725 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1726 //_ALLOC(pcf,sizeof(pCodeFunction));
1728 pcf->pc.type = PC_FUNCTION;
1729 pcf->pc.prev = pcf->pc.next = NULL;
1730 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1733 // pcf->pc.analyze = genericAnalyze;
1734 pcf->pc.destruct = genericDestruct;
1735 pcf->pc.print = pCodePrintFunction;
1740 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1741 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1742 strcpy(pcf->modname,mod);
1744 pcf->modname = NULL;
1747 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1748 pcf->fname = Safe_calloc(1,strlen(f)+1);
1749 strcpy(pcf->fname,f);
1753 return ( (pCode *)pcf);
1757 /*-----------------------------------------------------------------*/
1759 /*-----------------------------------------------------------------*/
1761 void destructpCodeFlow(pCode *pc)
1763 if(!pc || !isPCFL(pc))
1767 free(PCFL(pc)->uses);
1775 pCode *newpCodeFlow(void )
1779 //_ALLOC(pcflow,sizeof(pCodeFlow));
1780 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1782 pcflow->pc.type = PC_FLOW;
1783 pcflow->pc.prev = pcflow->pc.next = NULL;
1784 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1785 pcflow->pc.pb = NULL;
1787 // pcflow->pc.analyze = genericAnalyze;
1788 pcflow->pc.destruct = destructpCodeFlow;
1789 pcflow->pc.print = genericPrint;
1791 pcflow->pc.seq = GpcFlowSeq++;
1794 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1796 pcflow->from = pcflow->to = NULL;
1798 pcflow->inCond = PCC_NONE;
1799 pcflow->outCond = PCC_NONE;
1801 pcflow->firstBank = -1;
1802 pcflow->lastBank = -1;
1804 pcflow->FromConflicts = 0;
1805 pcflow->ToConflicts = 0;
1809 pcflow->registers = newSet();
1811 return ( (pCode *)pcflow);
1815 /*-----------------------------------------------------------------*/
1816 /*-----------------------------------------------------------------*/
1817 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1819 pCodeFlowLink *pcflowLink;
1821 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1823 pcflowLink->pcflow = pcflow;
1824 pcflowLink->bank_conflict = 0;
1829 /*-----------------------------------------------------------------*/
1830 /* newpCodeCSource - create a new pCode Source Symbol */
1831 /*-----------------------------------------------------------------*/
1833 pCode *newpCodeCSource(int ln, char *f, char *l)
1838 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1840 pccs->pc.type = PC_CSOURCE;
1841 pccs->pc.prev = pccs->pc.next = NULL;
1844 pccs->pc.destruct = genericDestruct;
1845 pccs->pc.print = genericPrint;
1847 pccs->line_number = ln;
1849 pccs->line = Safe_strdup(l);
1854 pccs->file_name = Safe_strdup(f);
1856 pccs->file_name = NULL;
1858 return ( (pCode *)pccs);
1861 /*-----------------------------------------------------------------*/
1862 /* pCodeLabelDestruct - free memory used by a label. */
1863 /*-----------------------------------------------------------------*/
1864 static void pCodeLabelDestruct(pCode *pc)
1870 if((pc->type == PC_LABEL) && PCL(pc)->label)
1871 free(PCL(pc)->label);
1877 pCode *newpCodeLabel(char *name, int key)
1883 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1885 pcl->pc.type = PC_LABEL;
1886 pcl->pc.prev = pcl->pc.next = NULL;
1887 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1890 // pcl->pc.analyze = genericAnalyze;
1891 pcl->pc.destruct = pCodeLabelDestruct;
1892 pcl->pc.print = pCodePrintLabel;
1898 sprintf(s,"_%05d_DS_",key);
1903 pcl->label = Safe_strdup(s);
1906 return ( (pCode *)pcl);
1911 /*-----------------------------------------------------------------*/
1912 /* newpBlock - create and return a pointer to a new pBlock */
1913 /*-----------------------------------------------------------------*/
1914 pBlock *newpBlock(void)
1919 PpB = Safe_calloc(1,sizeof(pBlock) );
1920 PpB->next = PpB->prev = NULL;
1922 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1923 PpB->tregisters = NULL;
1925 PpB->FlowTree = NULL;
1931 /*-----------------------------------------------------------------*/
1932 /* newpCodeChain - create a new chain of pCodes */
1933 /*-----------------------------------------------------------------*
1935 * This function will create a new pBlock and the pointer to the
1936 * pCode that is passed in will be the first pCode in the block.
1937 *-----------------------------------------------------------------*/
1940 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1943 pBlock *pB = newpBlock();
1945 pB->pcHead = pB->pcTail = pc;
1952 /*-----------------------------------------------------------------*/
1953 /* newpCodeOpLabel - Create a new label given the key */
1954 /* Note, a negative key means that the label is part of wild card */
1955 /* (and hence a wild card label) used in the pCodePeep */
1956 /* optimizations). */
1957 /*-----------------------------------------------------------------*/
1959 pCodeOp *newpCodeOpLabel(char *name, int key)
1962 static int label_key=-1;
1966 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1967 pcop->type = PO_LABEL;
1972 sprintf(s=buffer,"_%05d_DS_",key);
1974 s = name, key = label_key--;
1977 pcop->name = Safe_strdup(s);
1979 ((pCodeOpLabel *)pcop)->key = key;
1984 /*-----------------------------------------------------------------*/
1985 /*-----------------------------------------------------------------*/
1986 pCodeOp *newpCodeOpLit(int lit)
1992 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1993 pcop->type = PO_LITERAL;
1997 sprintf(s,"0x%02x",lit);
1999 pcop->name = Safe_strdup(s);
2002 ((pCodeOpLit *)pcop)->lit = lit;
2007 /*-----------------------------------------------------------------*/
2008 /*-----------------------------------------------------------------*/
2009 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2013 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2014 pcop->type = PO_IMMEDIATE;
2016 regs *r = dirregWithName(name);
2017 pcop->name = Safe_strdup(name);
2020 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2021 PCOI(pcop)->rIdx = r->rIdx;
2023 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2024 PCOI(pcop)->rIdx = -1;
2026 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2031 PCOI(pcop)->index = index;
2032 PCOI(pcop)->offset = offset;
2033 PCOI(pcop)->_const = code_space;
2038 /*-----------------------------------------------------------------*/
2039 /*-----------------------------------------------------------------*/
2040 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2046 if(!pcwb || !subtype) {
2047 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2051 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2052 pcop->type = PO_WILD;
2053 sprintf(s,"%%%d",id);
2054 pcop->name = Safe_strdup(s);
2056 PCOW(pcop)->id = id;
2057 PCOW(pcop)->pcwb = pcwb;
2058 PCOW(pcop)->subtype = subtype;
2059 PCOW(pcop)->matched = NULL;
2064 /*-----------------------------------------------------------------*/
2065 /*-----------------------------------------------------------------*/
2066 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2070 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2071 pcop->type = PO_GPR_BIT;
2073 pcop->name = Safe_strdup(s);
2077 PCORB(pcop)->bit = bit;
2078 PCORB(pcop)->inBitSpace = inBitSpace;
2083 /*-----------------------------------------------------------------*
2084 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2086 * If rIdx >=0 then a specific register from the set of registers
2087 * will be selected. If rIdx <0, then a new register will be searched
2089 *-----------------------------------------------------------------*/
2091 pCodeOp *newpCodeOpReg(int rIdx)
2095 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2100 PCOR(pcop)->rIdx = rIdx;
2101 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2103 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2106 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2107 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2110 pcop->type = PCOR(pcop)->r->pc_type;
2115 pCodeOp *newpCodeOpRegFromStr(char *name)
2119 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2120 PCOR(pcop)->r = allocRegByName(name, 1);
2121 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2122 pcop->type = PCOR(pcop)->r->pc_type;
2123 pcop->name = PCOR(pcop)->r->name;
2128 /*-----------------------------------------------------------------*/
2129 /*-----------------------------------------------------------------*/
2131 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2138 pcop = newpCodeOpBit(name, -1,0);
2142 pcop = newpCodeOpLit(-1);
2146 pcop = newpCodeOpLabel(NULL,-1);
2149 pcop = newpCodeOpReg(-1);
2153 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2156 pcop->name = Safe_strdup(name);
2164 /*-----------------------------------------------------------------*/
2165 /*-----------------------------------------------------------------*/
2166 void pCodeConstString(char *name, char *value)
2170 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2175 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2179 sprintf(buffer,"; %s = %s",name,value);
2181 addpCode2pBlock(pb,newpCodeCharP(buffer));
2182 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2185 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2191 /*-----------------------------------------------------------------*/
2192 /*-----------------------------------------------------------------*/
2193 void pCodeReadCodeTable(void)
2197 fprintf(stderr, " %s\n",__FUNCTION__);
2199 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2203 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2204 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2205 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2206 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2208 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2209 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2210 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2211 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2216 /*-----------------------------------------------------------------*/
2217 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2218 /*-----------------------------------------------------------------*/
2219 void addpCode2pBlock(pBlock *pb, pCode *pc)
2222 /* If this is the first pcode to be added to a block that
2223 * was initialized with a NULL pcode, then go ahead and
2224 * make this pcode the head and tail */
2225 pb->pcHead = pb->pcTail = pc;
2227 pb->pcTail->next = pc;
2228 pc->prev = pb->pcTail;
2235 /*-----------------------------------------------------------------*/
2236 /* addpBlock - place a pBlock into the pFile */
2237 /*-----------------------------------------------------------------*/
2238 void addpBlock(pBlock *pb)
2240 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2243 /* First time called, we'll pass through here. */
2244 //_ALLOC(the_pFile,sizeof(pFile));
2245 the_pFile = Safe_calloc(1,sizeof(pFile));
2246 the_pFile->pbHead = the_pFile->pbTail = pb;
2247 the_pFile->functions = NULL;
2251 the_pFile->pbTail->next = pb;
2252 pb->prev = the_pFile->pbTail;
2254 the_pFile->pbTail = pb;
2257 /*-----------------------------------------------------------------*/
2258 /* removepBlock - remove a pBlock from the pFile */
2259 /*-----------------------------------------------------------------*/
2260 void removepBlock(pBlock *pb)
2268 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2270 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2273 if(pbs == the_pFile->pbHead)
2274 the_pFile->pbHead = pbs->next;
2276 if (pbs == the_pFile->pbTail)
2277 the_pFile->pbTail = pbs->prev;
2280 pbs->next->prev = pbs->prev;
2283 pbs->prev->next = pbs->next;
2290 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2294 /*-----------------------------------------------------------------*/
2295 /* printpCode - write the contents of a pCode to a file */
2296 /*-----------------------------------------------------------------*/
2297 void printpCode(FILE *of, pCode *pc)
2308 fprintf(of,"warning - unable to print pCode\n");
2311 /*-----------------------------------------------------------------*/
2312 /* printpBlock - write the contents of a pBlock to a file */
2313 /*-----------------------------------------------------------------*/
2314 void printpBlock(FILE *of, pBlock *pb)
2324 for(pc = pb->pcHead; pc; pc = pc->next)
2329 /*-----------------------------------------------------------------*/
2331 /* pCode processing */
2335 /*-----------------------------------------------------------------*/
2337 void unlinkpCode(pCode *pc)
2343 fprintf(stderr,"Unlinking: ");
2344 printpCode(stderr, pc);
2347 pc->prev->next = pc->next;
2349 pc->next->prev = pc->prev;
2351 pc->prev = pc->next = NULL;
2355 /*-----------------------------------------------------------------*/
2356 /*-----------------------------------------------------------------*/
2358 static void genericDestruct(pCode *pc)
2364 /* For instructions, tell the register (if there's one used)
2365 * that it's no longer needed */
2366 regs *reg = getRegFromInstruction(pc);
2368 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2371 /* Instead of deleting the memory used by this pCode, mark
2372 * the object as bad so that if there's a pointer to this pCode
2373 * dangling around somewhere then (hopefully) when the type is
2374 * checked we'll catch it.
2379 addpCode2pBlock(pb_dead_pcodes, pc);
2386 /*-----------------------------------------------------------------*/
2387 /*-----------------------------------------------------------------*/
2388 void pBlockRegs(FILE *of, pBlock *pb)
2393 r = setFirstItem(pb->tregisters);
2395 r = setNextItem(pb->tregisters);
2400 /*-----------------------------------------------------------------*/
2401 /*-----------------------------------------------------------------*/
2402 char *get_op(pCodeOp *pcop,char *buffer, int size)
2407 int use_buffer = 1; // copy the string to the passed buffer pointer
2412 use_buffer = 0; // Don't bother copying the string to the buffer.
2416 switch(pcop->type) {
2420 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2423 return PCOR(pcop)->r->name;
2426 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2429 SAFE_snprintf(&buffer,&size,"%s",r->name);
2439 if(PCOI(pcop)->_const) {
2441 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2442 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2445 8 * PCOI(pcop)->offset );
2447 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2450 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2451 SAFE_snprintf(&s,&size,"(%s + %d)",
2453 PCOI(pcop)->index );
2455 SAFE_snprintf(&s,&size,"%s",pcop->name);
2462 //size = sizeof(buffer);
2463 if( PCOR(pcop)->instance) {
2464 SAFE_snprintf(&s,&size,"(%s + %d)",
2466 PCOR(pcop)->instance );
2467 //fprintf(stderr,"PO_DIR %s\n",buffer);
2469 SAFE_snprintf(&s,&size,"%s",pcop->name);
2475 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2484 return "NO operand";
2488 /*-----------------------------------------------------------------*/
2489 /*-----------------------------------------------------------------*/
2490 static char *get_op_from_instruction( pCodeInstruction *pcc)
2494 return get_op(pcc->pcop,NULL,0);
2496 return ("ERROR Null: "__FUNCTION__);
2500 /*-----------------------------------------------------------------*/
2501 /*-----------------------------------------------------------------*/
2502 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2505 fprintf(of,"pcodeopprint- not implemented\n");
2508 /*-----------------------------------------------------------------*/
2509 /*-----------------------------------------------------------------*/
2510 char *pCode2str(char *str, int size, pCode *pc)
2518 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2520 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2522 if(PCI(pc)->isBitInst) {
2523 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2524 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2525 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2526 PCI(pc)->pcop->name ,
2527 PCI(pc)->pcop->name );
2529 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2530 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2531 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2532 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2534 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2535 //PCI(pc)->pcop->t.bit );
2538 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2539 if( PCI(pc)->num_ops == 2)
2540 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2542 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2545 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2547 if( PCI(pc)->num_ops == 2)
2548 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2556 /* assuming that comment ends with a \n */
2557 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2561 /* assuming that inline code ends with a \n */
2562 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2566 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2569 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2572 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2575 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2578 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2582 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2589 /*-----------------------------------------------------------------*/
2590 /* genericPrint - the contents of a pCode to a file */
2591 /*-----------------------------------------------------------------*/
2592 static void genericPrint(FILE *of, pCode *pc)
2600 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2604 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2608 // If the opcode has a label, print that first
2610 pBranch *pbl = PCI(pc)->label;
2611 while(pbl && pbl->pc) {
2612 if(pbl->pc->type == PC_LABEL)
2613 pCodePrintLabel(of, pbl->pc);
2619 genericPrint(of,PCODE(PCI(pc)->cline));
2624 pCode2str(str, 256, pc);
2626 fprintf(of,"%s",str);
2629 fprintf(of, "\t;key=%03x",pc->seq);
2631 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2635 pBranch *dpb = pc->to; // debug
2637 switch ( dpb->pc->type) {
2639 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2642 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2645 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2648 fprintf(of, "\t;flow");
2662 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2663 if(PCW(pc)->pci.label)
2664 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2666 if(PCW(pc)->operand) {
2667 fprintf(of,";\toperand ");
2668 pCodeOpPrint(of,PCW(pc)->operand );
2673 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2677 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2681 fprintf(of,"unknown pCode type %d\n",pc->type);
2686 /*-----------------------------------------------------------------*/
2687 /* pCodePrintFunction - prints function begin/end */
2688 /*-----------------------------------------------------------------*/
2690 static void pCodePrintFunction(FILE *of, pCode *pc)
2696 if( ((pCodeFunction *)pc)->modname)
2697 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2699 if(PCF(pc)->fname) {
2700 pBranch *exits = PCF(pc)->to;
2702 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2705 exits = exits->next;
2708 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2711 if((PCF(pc)->from &&
2712 PCF(pc)->from->pc->type == PC_FUNCTION &&
2713 PCF(PCF(pc)->from->pc)->fname) )
2714 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2716 fprintf(of,"; exit point [can't find entry point]\n");
2719 /*-----------------------------------------------------------------*/
2720 /* pCodePrintLabel - prints label */
2721 /*-----------------------------------------------------------------*/
2723 static void pCodePrintLabel(FILE *of, pCode *pc)
2730 fprintf(of,"%s\n",PCL(pc)->label);
2731 else if (PCL(pc)->key >=0)
2732 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2734 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2737 /*-----------------------------------------------------------------*/
2738 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2739 /* remove it if it is found. */
2740 /*-----------------------------------------------------------------*/
2741 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2748 if(pcl->type == PC_OPCODE)
2749 b = PCI(pcl)->label;
2751 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2756 //fprintf (stderr, "%s \n",__FUNCTION__);
2757 //pcl->print(stderr,pcl);
2758 //pc->print(stderr,pc);
2761 //fprintf (stderr, "found label\n");
2765 bprev->next = b->next; /* Not first pCode in chain */
2769 PCI(pcl)->label = b->next; /* First pCode in chain */
2772 return; /* A label can't occur more than once */
2780 /*-----------------------------------------------------------------*/
2781 /*-----------------------------------------------------------------*/
2782 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2798 /*-----------------------------------------------------------------*/
2799 /* pBranchLink - given two pcodes, this function will link them */
2800 /* together through their pBranches */
2801 /*-----------------------------------------------------------------*/
2802 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2806 // Declare a new branch object for the 'from' pCode.
2808 //_ALLOC(b,sizeof(pBranch));
2809 b = Safe_calloc(1,sizeof(pBranch));
2810 b->pc = PCODE(t); // The link to the 'to' pCode.
2813 f->to = pBranchAppend(f->to,b);
2815 // Now do the same for the 'to' pCode.
2817 //_ALLOC(b,sizeof(pBranch));
2818 b = Safe_calloc(1,sizeof(pBranch));
2822 t->from = pBranchAppend(t->from,b);
2827 /*-----------------------------------------------------------------*/
2828 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2830 /*-----------------------------------------------------------------*/
2831 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2844 /*-----------------------------------------------------------------*/
2845 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2846 /*-----------------------------------------------------------------*/
2847 static void pCodeUnlink(pCode *pc)
2852 if(!pc->prev || !pc->next) {
2853 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2857 /* first remove the pCode from the chain */
2858 pc->prev->next = pc->next;
2859 pc->next->prev = pc->prev;
2861 /* Now for the hard part... */
2863 /* Remove the branches */
2867 pc1 = pb1->pc; /* Get the pCode that branches to the
2868 * one we're unlinking */
2870 /* search for the link back to this pCode (the one we're
2872 if(pb2 = pBranchFind(pc1->to,pc)) {
2873 pb2->pc = pc->to->pc; // make the replacement
2875 /* if the pCode we're unlinking contains multiple 'to'
2876 * branches (e.g. this a skip instruction) then we need
2877 * to copy these extra branches to the chain. */
2879 pBranchAppend(pb2, pc->to->next);
2888 /*-----------------------------------------------------------------*/
2889 /*-----------------------------------------------------------------*/
2891 static void genericAnalyze(pCode *pc)
2901 // Go through the pCodes that are in pCode chain and link
2902 // them together through the pBranches. Note, the pCodes
2903 // are linked together as a contiguous stream like the
2904 // assembly source code lines. The linking here mimics this
2905 // except that comments are not linked in.
2907 pCode *npc = pc->next;
2909 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2910 pBranchLink(pc,npc);
2915 /* reached the end of the pcode chain without finding
2916 * an instruction we could link to. */
2920 fprintf(stderr,"analyze PC_FLOW\n");
2924 fprintf(stderr,,";A bad pCode is being used\n");
2930 /*-----------------------------------------------------------------*/
2931 /*-----------------------------------------------------------------*/
2932 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2936 if(pc->type == PC_LABEL) {
2937 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2940 if(pc->type == PC_OPCODE) {
2941 pbr = PCI(pc)->label;
2943 if(pbr->pc->type == PC_LABEL) {
2944 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2954 /*-----------------------------------------------------------------*/
2955 /*-----------------------------------------------------------------*/
2956 int checkLabel(pCode *pc)
2960 if(pc && isPCI(pc)) {
2961 pbr = PCI(pc)->label;
2963 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2973 /*-----------------------------------------------------------------*/
2974 /* findLabelinpBlock - Search the pCode for a particular label */
2975 /*-----------------------------------------------------------------*/
2976 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2983 for(pc = pb->pcHead; pc; pc = pc->next)
2984 if(compareLabel(pc,pcop_label))
2990 /*-----------------------------------------------------------------*/
2991 /* findLabel - Search the pCode for a particular label */
2992 /*-----------------------------------------------------------------*/
2993 pCode * findLabel(pCodeOpLabel *pcop_label)
3001 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3002 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3006 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3010 /*-----------------------------------------------------------------*/
3011 /* findNextpCode - given a pCode, find the next of type 'pct' */
3012 /* in the linked list */
3013 /*-----------------------------------------------------------------*/
3014 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3027 /*-----------------------------------------------------------------*/
3028 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3029 /* in the linked list */
3030 /*-----------------------------------------------------------------*/
3031 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3043 /*-----------------------------------------------------------------*/
3044 /* findNextInstruction - given a pCode, find the next instruction */
3045 /* in the linked list */
3046 /*-----------------------------------------------------------------*/
3047 pCode * findNextInstruction(pCode *pci)
3052 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3056 fprintf(stderr,"findNextInstruction: ");
3057 printpCode(stderr, pc);
3062 //fprintf(stderr,"Couldn't find instruction\n");
3066 /*-----------------------------------------------------------------*/
3067 /* findNextInstruction - given a pCode, find the next instruction */
3068 /* in the linked list */
3069 /*-----------------------------------------------------------------*/
3070 pCode * findPrevInstruction(pCode *pci)
3072 return findPrevpCode(pci, PC_OPCODE);
3075 /*-----------------------------------------------------------------*/
3076 /* findFunctionEnd - given a pCode find the end of the function */
3077 /* that contains it */
3078 /*-----------------------------------------------------------------*/
3079 pCode * findFunctionEnd(pCode *pc)
3083 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3089 fprintf(stderr,"Couldn't find function end\n");
3094 /*-----------------------------------------------------------------*/
3095 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3096 /* instruction with which it is associated. */
3097 /*-----------------------------------------------------------------*/
3098 static void AnalyzeLabel(pCode *pc)
3107 static void AnalyzeGOTO(pCode *pc)
3110 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3114 static void AnalyzeSKIP(pCode *pc)
3117 pBranchLink(pc,findNextInstruction(pc->next));
3118 pBranchLink(pc,findNextInstruction(pc->next->next));
3122 static void AnalyzeRETURN(pCode *pc)
3125 // branch_link(pc,findFunctionEnd(pc->next));
3131 /*-----------------------------------------------------------------*/
3132 /*-----------------------------------------------------------------*/
3133 regs * getRegFromInstruction(pCode *pc)
3139 PCI(pc)->num_ops == 0 )
3142 switch(PCI(pc)->pcop->type) {
3145 return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3149 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3150 return PCOR(PCI(pc)->pcop)->r;
3153 if(PCOI(PCI(pc)->pcop)->r)
3154 return (PCOI(PCI(pc)->pcop)->r);
3156 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3157 return dirregWithName(PCI(pc)->pcop->name);
3158 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3161 return PCOR(PCI(pc)->pcop)->r;
3164 //fprintf(stderr, "getRegFromInstruction - dir\n");
3165 return PCOR(PCI(pc)->pcop)->r;
3167 //fprintf(stderr, "getRegFromInstruction - literal\n");
3171 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3172 //genericPrint(stderr, pc);
3180 /*-----------------------------------------------------------------*/
3181 /*-----------------------------------------------------------------*/
3183 void AnalyzepBlock(pBlock *pb)
3190 /* Find all of the registers used in this pBlock
3191 * by looking at each instruction and examining it's
3194 for(pc = pb->pcHead; pc; pc = pc->next) {
3196 /* Is this an instruction with operands? */
3197 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3199 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3201 /* Loop through all of the registers declared so far in
3202 this block and see if we find this one there */
3204 regs *r = setFirstItem(pb->tregisters);
3207 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3208 PCOR(PCI(pc)->pcop)->r = r;
3211 r = setNextItem(pb->tregisters);
3215 /* register wasn't found */
3216 //r = Safe_calloc(1, sizeof(regs));
3217 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3218 //addSet(&pb->tregisters, r);
3219 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3220 //PCOR(PCI(pc)->pcop)->r = r;
3221 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3223 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3226 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3227 if(PCOR(PCI(pc)->pcop)->r) {
3228 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3229 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3231 if(PCI(pc)->pcop->name)
3232 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3234 fprintf(stderr,"ERROR: NULL register\n");
3243 /*-----------------------------------------------------------------*/
3245 /*-----------------------------------------------------------------*/
3246 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3248 void InsertpFlow(pCode *pc, pCode **pflow)
3250 PCFL(*pflow)->end = pc;
3252 if(!pc || !pc->next)
3255 *pflow = newpCodeFlow();
3256 pCodeInsertAfter(pc, *pflow);
3259 /*-----------------------------------------------------------------*/
3260 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3261 /* the flow blocks. */
3263 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3264 * point the instruction flow changes.
3266 /*-----------------------------------------------------------------*/
3267 void BuildFlow(pBlock *pb)
3270 pCode *last_pci=NULL;
3277 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3278 /* Insert a pCodeFlow object at the beginning of a pBlock */
3280 pflow = newpCodeFlow(); /* Create a new Flow object */
3281 pflow->next = pb->pcHead; /* Make the current head the next object */
3282 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3283 pb->pcHead = pflow; /* Make the Flow object the head */
3286 for( pc = findNextInstruction(pb->pcHead);
3288 pc=findNextInstruction(pc)) {
3291 PCI(pc)->pcflow = PCFL(pflow);
3293 //fprintf(stderr," build: ");
3294 //pflow->print(stderr,pflow);
3296 if( PCI(pc)->isSkip) {
3298 /* The two instructions immediately following this one
3299 * mark the beginning of a new flow segment */
3301 while(pc && PCI(pc)->isSkip) {
3303 PCI(pc)->pcflow = PCFL(pflow);
3307 InsertpFlow(pc, &pflow);
3308 pc=findNextInstruction(pc->next);
3316 PCI(pc)->pcflow = PCFL(pflow);
3318 InsertpFlow(pc, &pflow);
3320 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3322 InsertpFlow(pc, &pflow);
3325 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3327 /* This instruction marks the beginning of a
3328 * new flow segment */
3332 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3334 PCI(pc)->pcflow = PCFL(pflow);
3341 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3342 PCFL(pflow)->end = pb->pcTail;
3345 /*-------------------------------------------------------------------*/
3346 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3347 /* the flow blocks. */
3349 * unBuildFlow removes pCodeFlow objects from a pCode chain
3351 /*-----------------------------------------------------------------*/
3352 void unBuildFlow(pBlock *pb)
3361 pCode *pcn = pc->next;
3365 PCI(pc)->pcflow = NULL;
3367 } else if(isPCFL(pc)) {
3377 /*-----------------------------------------------------------------*/
3378 /*-----------------------------------------------------------------*/
3379 void dumpCond(int cond)
3382 static char *pcc_str[] = {
3396 int ncond = sizeof(pcc_str) / sizeof(char *);
3399 fprintf(stderr, "0x%04X\n",cond);
3401 for(i=0,j=1; i<ncond; i++, j<<=1)
3403 fprintf(stderr, " %s\n",pcc_str[i]);
3407 /*-----------------------------------------------------------------*/
3408 /*-----------------------------------------------------------------*/
3409 void FlowStats(pCodeFlow *pcflow)
3417 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3419 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3422 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3427 fprintf(stderr, " FlowStats inCond: ");
3428 dumpCond(pcflow->inCond);
3429 fprintf(stderr, " FlowStats outCond: ");
3430 dumpCond(pcflow->outCond);
3434 /*-----------------------------------------------------------------*
3435 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3436 * if it affects the banking bits.
3438 * return: -1 == Banking bits are unaffected by this pCode.
3440 * return: > 0 == Banking bits are affected.
3442 * If the banking bits are affected, then the returned value describes
3443 * which bits are affected and how they're affected. The lower half
3444 * of the integer maps to the bits that are affected, the upper half
3445 * to whether they're set or cleared.
3447 *-----------------------------------------------------------------*/
3448 #define SET_BANK_BIT (1 << 16)
3449 #define CLR_BANK_BIT 0
3451 int isBankInstruction(pCode *pc)
3459 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3461 /* Check to see if the register banks are changing */
3462 if(PCI(pc)->isModReg) {
3464 pCodeOp *pcop = PCI(pc)->pcop;
3465 switch(PCI(pc)->op) {
3468 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3469 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3470 return SET_BANK_BIT | PIC_RP0_BIT;
3473 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3474 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3475 return CLR_BANK_BIT | PIC_RP0_BIT;
3480 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3481 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3482 return CLR_BANK_BIT | PIC_RP1_BIT;
3484 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3485 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3486 return CLR_BANK_BIT | PIC_RP1_BIT;
3490 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3491 //genericPrint(stderr, pc);
3502 /*-----------------------------------------------------------------*/
3503 /*-----------------------------------------------------------------*/
3504 void FillFlow(pCodeFlow *pcflow)
3513 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3515 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3518 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3525 isBankInstruction(pc);
3527 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3531 fprintf(stderr, " FillFlow - Bad end of flow\n");
3533 fprintf(stderr, " FillFlow - Ending flow with\n ");
3534 pc->print(stderr,pc);
3537 fprintf(stderr, " FillFlow inCond: ");
3538 dumpCond(pcflow->inCond);
3539 fprintf(stderr, " FillFlow outCond: ");
3540 dumpCond(pcflow->outCond);
3544 /*-----------------------------------------------------------------*/
3545 /*-----------------------------------------------------------------*/
3546 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3548 pCodeFlowLink *fromLink, *toLink;
3550 if(!from || !to || !to->pcflow || !from->pcflow)
3553 fromLink = newpCodeFlowLink(from->pcflow);
3554 toLink = newpCodeFlowLink(to->pcflow);
3556 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3557 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3561 /*-----------------------------------------------------------------*/
3562 /*-----------------------------------------------------------------*/
3563 void LinkFlow(pBlock *pb)
3569 //fprintf(stderr,"linkflow \n");
3571 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3573 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3576 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3578 //fprintf(stderr," link: ");
3579 //pcflow->print(stderr,pcflow);
3581 //FillFlow(PCFL(pcflow));
3583 pc = PCFL(pcflow)->end;
3585 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3586 if(isPCI_SKIP(pc)) {
3587 //fprintf(stderr, "ends with skip\n");
3588 //pc->print(stderr,pc);
3589 pct=findNextInstruction(pc->next);
3590 LinkFlow_pCode(PCI(pc),PCI(pct));
3591 pct=findNextInstruction(pct->next);
3592 LinkFlow_pCode(PCI(pc),PCI(pct));
3596 if(isPCI_BRANCH(pc)) {
3597 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3599 //fprintf(stderr, "ends with branch\n ");
3600 //pc->print(stderr,pc);
3602 if(!(pcol && isPCOLAB(pcol))) {
3603 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3604 pc->print(stderr,pc);
3605 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3610 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3611 LinkFlow_pCode(PCI(pc),PCI(pct));
3613 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3619 //fprintf(stderr, "ends with non-branching instruction:\n");
3620 //pc->print(stderr,pc);
3622 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3628 //fprintf(stderr, "ends with unknown\n");
3629 //pc->print(stderr,pc);
3633 //fprintf(stderr, "ends with nothing: ERROR\n");
3638 /*-----------------------------------------------------------------*/
3639 /*-----------------------------------------------------------------*/
3640 int isPCinFlow(pCode *pc, pCode *pcflow)
3646 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3649 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3655 /*-----------------------------------------------------------------*/
3656 /*-----------------------------------------------------------------*/
3657 void BanksUsedFlow2(pCode *pcflow)
3666 if(!isPCFL(pcflow)) {
3667 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3671 pc = findNextInstruction(pcflow->next);
3673 PCFL(pcflow)->lastBank = -1;
3675 while(isPCinFlow(pc,pcflow)) {
3677 int bank_selected = isBankInstruction(pc);
3679 //if(PCI(pc)->pcflow)
3680 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3682 if(bank_selected > 0) {
3683 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3685 /* This instruction is modifying banking bits before accessing registers */
3687 PCFL(pcflow)->firstBank = -1;
3689 if(PCFL(pcflow)->lastBank == -1)
3690 PCFL(pcflow)->lastBank = 0;
3692 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3693 if(bank_selected & SET_BANK_BIT)
3694 PCFL(pcflow)->lastBank |= bank;
3698 reg = getRegFromInstruction(pc);
3700 if(reg && !isREGinBank(reg, bank)) {
3701 int allbanks = REGallBanks(reg);
3703 PCFL(pcflow)->firstBank = allbanks;
3705 PCFL(pcflow)->lastBank = allbanks;
3712 pc = findNextInstruction(pc->next);
3715 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3716 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3721 /*-----------------------------------------------------------------*/
3722 /*-----------------------------------------------------------------*/
3723 void BanksUsedFlow(pBlock *pb)
3728 //pb->pcHead->print(stderr, pb->pcHead);
3730 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3731 //pcflow->print(stderr,pcflow);
3733 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3735 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3737 BanksUsedFlow2(pcflow);
3743 /*-----------------------------------------------------------------*/
3744 /*-----------------------------------------------------------------*/
3745 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3753 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3755 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3756 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3758 pCodeInsertAfter(pc->prev, new_pc);
3760 /* Move the label, if there is one */
3762 if(PCI(pc)->label) {
3763 PCI(new_pc)->label = PCI(pc)->label;
3764 PCI(pc)->label = NULL;
3767 /* The new instruction has the same pcflow block */
3768 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3771 /*-----------------------------------------------------------------*/
3772 /*-----------------------------------------------------------------*/
3773 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3784 pc = findNextInstruction(pcfl->pc.next);
3786 while(isPCinFlow(pc,PCODE(pcfl))) {
3789 reg = getRegFromInstruction(pc);
3792 fprintf(stderr, " %s ",reg->name);
3793 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3798 if(reg && REG_BANK(reg)!=cur_bank) {
3799 /* Examine the instruction before this one to make sure it is
3800 * not a skip type instruction */
3801 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3802 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3803 int b = cur_bank ^ REG_BANK(reg);
3805 //fprintf(stderr, "Cool! can switch banks\n");
3806 cur_bank = REG_BANK(reg);
3811 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3814 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3815 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3819 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3820 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3822 insertBankSwitch(pc, -1, -1);
3825 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3826 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3827 pCodeInsertAfter(pc->prev, new_pc);
3828 if(PCI(pc)->label) {
3829 PCI(new_pc)->label = PCI(pc)->label;
3830 PCI(pc)->label = NULL;
3834 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3835 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3836 pCodeInsertAfter(pc, new_pc);
3842 //fprintf(stderr, "Bummer can't switch banks\n");
3848 pc = findNextInstruction(pc->next);
3852 if(pcprev && cur_bank) {
3853 /* Brute force - make sure that we point to bank 0 at the
3854 * end of each flow block */
3855 new_pc = newpCode(POC_BCF,
3856 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3857 pCodeInsertAfter(pcprev, new_pc);
3863 /*-----------------------------------------------------------------*/
3864 /*int compareBankFlow - compare the banking requirements between */
3866 /*-----------------------------------------------------------------*/
3867 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3870 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3873 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3876 if(pcflow->firstBank == -1)
3880 if(pcflowLink->pcflow->firstBank == -1) {
3881 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3882 pcflowLink->pcflow->to :
3883 pcflowLink->pcflow->from);
3884 return compareBankFlow(pcflow, pctl, toORfrom);
3888 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3891 pcflowLink->bank_conflict++;
3892 pcflowLink->pcflow->FromConflicts++;
3893 pcflow->ToConflicts++;
3896 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3899 pcflowLink->bank_conflict++;
3900 pcflowLink->pcflow->ToConflicts++;
3901 pcflow->FromConflicts++;
3905 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3906 pcflowLink->pcflow->pc.seq,
3907 pcflowLink->pcflow->FromConflicts,
3908 pcflowLink->pcflow->ToConflicts);
3913 /*-----------------------------------------------------------------*/
3914 /*-----------------------------------------------------------------*/
3915 void FixBankFlow(pBlock *pb)
3919 pCodeFlowLink *pcfl;
3921 pCode *pcflow_max_To=NULL;
3922 pCode *pcflow_max_From=NULL;
3923 int max_ToConflicts=0;
3924 int max_FromConflicts=0;
3926 //fprintf(stderr,"Fix Bank flow \n");
3927 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3931 First loop through all of the flow objects in this pcode block
3932 and fix the ones that have banking conflicts between the
3936 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3938 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3940 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3942 if(!isPCFL(pcflow)) {
3943 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3947 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3948 PCFL(pcflow)->firstBank >= 0 &&
3949 PCFL(pcflow)->lastBank >= 0 ) {
3951 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3952 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3954 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3955 BanksUsedFlow2(pcflow);
3960 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3962 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3964 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3969 if(!isPCFL(pcflow)) {
3970 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3974 PCFL(pcflow)->FromConflicts = 0;
3975 PCFL(pcflow)->ToConflicts = 0;
3980 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3981 pcfl = setFirstItem(PCFL(pcflow)->from);
3984 pc = PCODE(pcfl->pcflow);
3987 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3988 pc->print(stderr,pc);
3991 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3994 pcfl=setNextItem(PCFL(pcflow)->from);
3997 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3998 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4000 FixRegisterBankingInFlow(PCFL(pcflow),0);
4001 BanksUsedFlow2(pcflow);
4003 continue; /* Don't need to check the flow from here - it's already been fixed */
4010 pcfl = setFirstItem(PCFL(pcflow)->to);
4013 pc = PCODE(pcfl->pcflow);
4015 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4016 pc->print(stderr,pc);
4019 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4022 pcfl=setNextItem(PCFL(pcflow)->to);
4025 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4026 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4028 FixRegisterBankingInFlow(PCFL(pcflow),0);
4029 BanksUsedFlow2(pcflow);
4034 Loop through the flow objects again and find the ones with the
4038 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4040 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4042 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4043 pcflow_max_To = pcflow;
4045 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4046 pcflow_max_From = pcflow;
4050 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4051 PCFL(pcflow_max_To)->pc.seq,
4052 PCFL(pcflow_max_To)->ToConflicts);
4055 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4056 PCFL(pcflow_max_From)->pc.seq,
4057 PCFL(pcflow_max_From)->FromConflicts);
4061 /*-----------------------------------------------------------------*/
4062 /*-----------------------------------------------------------------*/
4063 void DumpFlow(pBlock *pb)
4067 pCodeFlowLink *pcfl;
4070 fprintf(stderr,"Dump flow \n");
4071 pb->pcHead->print(stderr, pb->pcHead);
4073 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4074 pcflow->print(stderr,pcflow);
4076 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4078 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4080 if(!isPCFL(pcflow)) {
4081 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4084 fprintf(stderr,"dumping: ");
4085 pcflow->print(stderr,pcflow);
4086 FlowStats(PCFL(pcflow));
4088 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4090 pc = PCODE(pcfl->pcflow);
4092 fprintf(stderr, " from seq %d:\n",pc->seq);
4094 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4095 pc->print(stderr,pc);
4100 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4102 pc = PCODE(pcfl->pcflow);
4104 fprintf(stderr, " to seq %d:\n",pc->seq);
4106 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4107 pc->print(stderr,pc);
4116 /*-----------------------------------------------------------------*/
4117 /*-----------------------------------------------------------------*/
4118 int OptimizepBlock(pBlock *pb)
4123 if(!pb || !peepOptimizing)
4126 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4128 for(pc = pb->pcHead; pc; pc = pc->next)
4129 matches += pCodePeepMatchRule(pc);
4132 pc = findNextInstruction(pb->pcHead);
4137 if(pCodePeepMatchRule(pc)) {
4142 pc = findNextInstruction(pcprev->next);
4144 pc = findNextInstruction(pb->pcHead);
4146 pc = findNextInstruction(pc->next);
4150 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4155 /*-----------------------------------------------------------------*/
4156 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4157 /*-----------------------------------------------------------------*/
4158 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4162 for(pc = pcs; pc; pc = pc->next) {
4164 if((pc->type == PC_OPCODE) &&
4166 (PCI(pc)->pcop->type == PO_LABEL) &&
4167 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4175 /*-----------------------------------------------------------------*/
4176 /*-----------------------------------------------------------------*/
4177 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4182 (PCI(pc)->pcop->type == PO_LABEL)) {
4184 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4186 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4188 free(pcol->pcop.name);
4190 sprintf(buffer,"_%05d_DS_",pcl->key);
4192 pcol->pcop.name = Safe_strdup(buffer);
4193 pcol->key = pcl->key;
4194 //pc->print(stderr,pc);
4201 /*-----------------------------------------------------------------*/
4202 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4203 /* pCode chain if they're not used. */
4204 /*-----------------------------------------------------------------*/
4205 void pBlockRemoveUnusedLabels(pBlock *pb)
4207 pCode *pc; pCodeLabel *pcl;
4212 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4214 pBranch *pbr = PCI(pc)->label;
4215 if(pbr && pbr->next) {
4216 pCode *pcd = pb->pcHead;
4218 //fprintf(stderr, "multiple labels\n");
4219 //pc->print(stderr,pc);
4224 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4225 //fprintf(stderr,"Used by:\n");
4226 //pcd->print(stderr,pcd);
4228 exchangeLabels(PCL(pbr->pc),pcd);
4237 for(pc = pb->pcHead; pc; pc = pc->next) {
4239 if(isPCL(pc)) // pc->type == PC_LABEL)
4241 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4242 pcl = PCL(PCI(pc)->label->pc);
4245 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4247 /* This pCode is a label, so search the pBlock to see if anyone
4250 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4251 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4252 /* Couldn't find an instruction that refers to this label
4253 * So, unlink the pCode label from it's pCode chain
4254 * and destroy the label */
4255 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4257 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4258 if(pc->type == PC_LABEL) {
4260 pCodeLabelDestruct(pc);
4262 unlinkpCodeFromBranch(pc, PCODE(pcl));
4263 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4274 /*-----------------------------------------------------------------*/
4275 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4276 /* chain and put them into pBranches that are */
4277 /* associated with the appropriate pCode */
4279 /*-----------------------------------------------------------------*/
4280 void pBlockMergeLabels(pBlock *pb)
4283 pCode *pc, *pcnext=NULL;
4288 /* First, Try to remove any unused labels */
4289 //pBlockRemoveUnusedLabels(pb);
4291 /* Now loop through the pBlock and merge the labels with the opcodes */
4293 for(pc = pb->pcHead; pc; pc = pc->next) {
4295 if(pc->type == PC_LABEL) {
4297 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4298 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4299 if((pcnext = findNextInstruction(pc) )) {
4301 pCode *pcn = pc->next;
4303 // Unlink the pCode label from it's pCode chain
4306 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4307 // And link it into the instruction's pBranch labels. (Note, since
4308 // it's possible to have multiple labels associated with one instruction
4309 // we must provide a means to accomodate the additional labels. Thus
4310 // the labels are placed into the singly-linked list "label" as
4311 // opposed to being a single member of the pCodeInstruction.)
4313 //_ALLOC(pbr,sizeof(pBranch));
4314 pbr = Safe_calloc(1,sizeof(pBranch));
4319 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4324 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4326 } else if(pc->type == PC_CSOURCE) {
4328 /* merge the source line symbolic info into the next instruction */
4329 if((pcnext = findNextInstruction(pc) )) {
4331 pCode *pcn = pc->next;
4333 // Unlink the pCode label from it's pCode chain
4335 PCI(pcnext)->cline = PCCS(pc);
4336 //fprintf(stderr, "merging CSRC\n");
4337 //genericPrint(stderr,pcnext);
4344 pBlockRemoveUnusedLabels(pb);
4348 /*-----------------------------------------------------------------*/
4349 /*-----------------------------------------------------------------*/
4350 int OptimizepCode(char dbName)
4352 #define MAX_PASSES 4
4361 DFPRINTF((stderr," Optimizing pCode\n"));
4365 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4366 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4367 matches += OptimizepBlock(pb);
4370 while(matches && ++passes < MAX_PASSES);
4375 /*-----------------------------------------------------------------*/
4376 /* popCopyGPR2Bit - copy a pcode operator */
4377 /*-----------------------------------------------------------------*/
4379 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4383 pcop = newpCodeOpBit(pc->name, bitval, 0);
4385 if( !( (pcop->type == PO_LABEL) ||
4386 (pcop->type == PO_LITERAL) ||
4387 (pcop->type == PO_STR) ))
4388 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4396 /*-----------------------------------------------------------------*/
4397 /*-----------------------------------------------------------------*/
4398 int InstructionRegBank(pCode *pc)
4402 if( (reg = getRegFromInstruction(pc)) == NULL)
4405 return REG_BANK(reg);
4410 /*-----------------------------------------------------------------*/
4411 /*-----------------------------------------------------------------*/
4412 void FixRegisterBanking(pBlock *pb)
4424 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4425 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4428 /* loop through all of the flow blocks with in one pblock */
4430 //fprintf(stderr,"Register banking\n");
4433 /* at this point, pc should point to a PC_FLOW object */
4436 /* for each flow block, determine the register banking
4441 //genericPrint(stderr, pc);
4443 reg = getRegFromInstruction(pc);
4446 fprintf(stderr, " %s ",reg->name);
4447 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4451 if(reg && REG_BANK(reg)!=cur_bank) {
4452 /* Examine the instruction before this one to make sure it is
4453 * not a skip type instruction */
4454 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4455 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4456 int b = cur_bank ^ REG_BANK(reg);
4458 //fprintf(stderr, "Cool! can switch banks\n");
4459 cur_bank = REG_BANK(reg);
4461 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4462 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4463 pCodeInsertAfter(pc->prev, new_pc);
4464 if(PCI(pc)->label) {
4465 PCI(new_pc)->label = PCI(pc)->label;
4466 PCI(pc)->label = NULL;
4469 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4470 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4471 pCodeInsertAfter(pc, new_pc);
4477 //fprintf(stderr, "Bummer can't switch banks\n");
4485 // } while(pc && !(isPCFL(pc)));
4490 if(pcprev && cur_bank) {
4491 /* Brute force - make sure that we point to bank 0 at the
4492 * end of each flow block */
4493 new_pc = newpCode(POC_BCF,
4494 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4495 pCodeInsertAfter(pcprev, new_pc);
4501 void pBlockDestruct(pBlock *pb)
4512 /*-----------------------------------------------------------------*/
4513 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4514 /* name dbName and combine them */
4515 /* into one block */
4516 /*-----------------------------------------------------------------*/
4517 void mergepBlocks(char dbName)
4520 pBlock *pb, *pbmerged = NULL,*pbn;
4522 pb = the_pFile->pbHead;
4524 //fprintf(stderr," merging blocks named %c\n",dbName);
4528 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4529 if( getpBlock_dbName(pb) == dbName) {
4531 //fprintf(stderr," merged block %c\n",dbName);
4536 addpCode2pBlock(pbmerged, pb->pcHead);
4537 /* addpCode2pBlock doesn't handle the tail: */
4538 pbmerged->pcTail = pb->pcTail;
4540 pb->prev->next = pbn;
4542 pbn->prev = pb->prev;
4547 //printpBlock(stderr, pbmerged);
4554 /*-----------------------------------------------------------------*/
4555 /* AnalyzeBanking - Called after the memory addresses have been */
4556 /* assigned to the registers. */
4558 /*-----------------------------------------------------------------*/
4559 void AnalyzeBanking(void)
4568 /* Phase 2 - Flow Analysis - Register Banking
4570 * In this phase, the individual flow blocks are examined
4571 * and register banking is fixed.
4574 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4575 //FixRegisterBanking(pb);
4577 /* Phase 2 - Flow Analysis
4579 * In this phase, the pCode is partition into pCodeFlow
4580 * blocks. The flow blocks mark the points where a continuous
4581 * stream of instructions changes flow (e.g. because of
4582 * a call or goto or whatever).
4585 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4589 /* Phase 2 - Flow Analysis - linking flow blocks
4591 * In this phase, the individual flow blocks are examined
4592 * to determine their order of excution.
4595 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4598 /* Phase 3 - Flow Analysis - Flow Tree
4600 * In this phase, the individual flow blocks are examined
4601 * to determine their order of excution.
4604 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4608 /* Phase x - Flow Analysis - Used Banks
4610 * In this phase, the individual flow blocks are examined
4611 * to determine the Register Banks they use
4614 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4617 /* Phase x - Flow Analysis - Used Banks
4619 * In this phase, the individual flow blocks are examined
4620 * to determine the Register Banks they use
4623 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4627 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4628 pCodeRegMapLiveRanges(pb);
4630 RemoveUnusedRegisters();
4632 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4633 pCodeRegOptimizeRegUsage();
4638 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4642 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4644 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4645 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4646 pcflow = pcflow->next) {
4648 FillFlow(PCFL(pcflow));
4652 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4654 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4655 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4656 pcflow = pcflow->next) {
4658 FlowStats(PCFL(pcflow));
4664 /*-----------------------------------------------------------------*/
4665 /* buildCallTree - look at the flow and extract all of the calls */
4667 /*-----------------------------------------------------------------*/
4668 set *register_usage(pBlock *pb);
4670 void buildCallTree(void )
4681 /* Now build the call tree.
4682 First we examine all of the pCodes for functions.
4683 Keep in mind that the function boundaries coincide
4684 with pBlock boundaries.
4686 The algorithm goes something like this:
4687 We have two nested loops. The outer loop iterates
4688 through all of the pBlocks/functions. The inner
4689 loop iterates through all of the pCodes for
4690 a given pBlock. When we begin iterating through
4691 a pBlock, the variable pc_fstart, pCode of the start
4692 of a function, is cleared. We then search for pCodes
4693 of type PC_FUNCTION. When one is encountered, we
4694 initialize pc_fstart to this and at the same time
4695 associate a new pBranch object that signifies a
4696 branch entry. If a return is found, then this signifies
4697 a function exit point. We'll link the pCodes of these
4698 returns to the matching pc_fstart.
4700 When we're done, a doubly linked list of pBranches
4701 will exist. The head of this list is stored in
4702 `the_pFile', which is the meta structure for all
4703 of the pCode. Look at the printCallTree function
4704 on how the pBranches are linked together.
4707 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4708 pCode *pc_fstart=NULL;
4709 for(pc = pb->pcHead; pc; pc = pc->next) {
4711 if (PCF(pc)->fname) {
4713 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4714 //fprintf(stderr," found main \n");
4715 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4719 pbr = Safe_calloc(1,sizeof(pBranch));
4720 pbr->pc = pc_fstart = pc;
4723 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4725 // Here's a better way of doing the same:
4726 addSet(&pb->function_entries, pc);
4729 // Found an exit point in a function, e.g. return
4730 // (Note, there may be more than one return per function)
4732 pBranchLink(PCF(pc_fstart), PCF(pc));
4734 addSet(&pb->function_exits, pc);
4736 } else if(isCALL(pc)) {
4737 addSet(&pb->function_calls,pc);
4742 /* Re-allocate the registers so that there are no collisions
4743 * between local variables when one function call another */
4746 // pic14_deallocateAllRegs();
4748 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4755 /*-----------------------------------------------------------------*/
4756 /* AnalyzepCode - parse the pCode that has been generated and form */
4757 /* all of the logical connections. */
4759 /* Essentially what's done here is that the pCode flow is */
4761 /*-----------------------------------------------------------------*/
4763 void AnalyzepCode(char dbName)
4774 /* Phase 1 - Register allocation and peep hole optimization
4776 * The first part of the analysis is to determine the registers
4777 * that are used in the pCode. Once that is done, the peep rules
4778 * are applied to the code. We continue to loop until no more
4779 * peep rule optimizations are found (or until we exceed the
4780 * MAX_PASSES threshold).
4782 * When done, the required registers will be determined.
4788 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4789 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4791 /* First, merge the labels with the instructions */
4792 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4793 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4795 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4796 //fprintf(stderr," analyze and merging block %c\n",dbName);
4797 pBlockMergeLabels(pb);
4800 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4804 changes = OptimizepCode(dbName);
4806 } while(changes && (i++ < MAX_PASSES));
4811 /*-----------------------------------------------------------------*/
4812 /* ispCodeFunction - returns true if *pc is the pCode of a */
4814 /*-----------------------------------------------------------------*/
4815 bool ispCodeFunction(pCode *pc)
4818 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4824 /*-----------------------------------------------------------------*/
4825 /* findFunction - Search for a function by name (given the name) */
4826 /* in the set of all functions that are in a pBlock */
4827 /* (note - I expect this to change because I'm planning to limit */
4828 /* pBlock's to just one function declaration */
4829 /*-----------------------------------------------------------------*/
4830 pCode *findFunction(char *fname)
4837 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4839 pc = setFirstItem(pb->function_entries);
4842 if((pc->type == PC_FUNCTION) &&
4844 (strcmp(fname, PCF(pc)->fname)==0))
4847 pc = setNextItem(pb->function_entries);
4855 void MarkUsedRegisters(set *regset)
4860 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4861 r2 = pic14_regWithIdx(r1->rIdx);
4867 void pBlockStats(FILE *of, pBlock *pb)
4873 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4875 // for now just print the first element of each set
4876 pc = setFirstItem(pb->function_entries);
4878 fprintf(of,";entry: ");
4881 pc = setFirstItem(pb->function_exits);
4883 fprintf(of,";has an exit\n");
4887 pc = setFirstItem(pb->function_calls);
4889 fprintf(of,";functions called:\n");
4892 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4893 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4895 pc = setNextItem(pb->function_calls);
4899 r = setFirstItem(pb->tregisters);
4901 int n = elementsInSet(pb->tregisters);
4903 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4906 fprintf(of,"; %s\n",r->name);
4907 r = setNextItem(pb->tregisters);
4912 /*-----------------------------------------------------------------*/
4913 /*-----------------------------------------------------------------*/
4915 static void sequencepCode(void)
4921 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4923 pb->seq = GpCodeSequenceNumber+1;
4925 for( pc = pb->pcHead; pc; pc = pc->next)
4926 pc->seq = ++GpCodeSequenceNumber;
4932 /*-----------------------------------------------------------------*/
4933 /*-----------------------------------------------------------------*/
4934 set *register_usage(pBlock *pb)
4937 set *registers=NULL;
4938 set *registersInCallPath = NULL;
4940 /* check recursion */
4942 pc = setFirstItem(pb->function_entries);
4949 if(pc->type != PC_FUNCTION)
4950 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4952 pc = setFirstItem(pb->function_calls);
4953 for( ; pc; pc = setNextItem(pb->function_calls)) {
4955 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4956 char *dest = get_op_from_instruction(PCI(pc));
4958 pcn = findFunction(dest);
4960 registersInCallPath = register_usage(pcn->pb);
4962 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4967 pBlockStats(stderr,pb); // debug
4970 // Mark the registers in this block as used.
4972 MarkUsedRegisters(pb->tregisters);
4973 if(registersInCallPath) {
4974 /* registers were used in the functions this pBlock has called */
4975 /* so now, we need to see if these collide with the ones we are */
4978 regs *r1,*r2, *newreg;
4980 DFPRINTF((stderr,"comparing registers\n"));
4982 r1 = setFirstItem(registersInCallPath);
4985 r2 = setFirstItem(pb->tregisters);
4987 while(r2 && (r1->type != REG_STK)) {
4989 if(r2->rIdx == r1->rIdx) {
4990 newreg = pic14_findFreeReg(REG_GPR);
4994 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4998 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4999 r1->rIdx, newreg->rIdx));
5000 r2->rIdx = newreg->rIdx;
5001 //if(r2->name) free(r2->name);
5003 r2->name = Safe_strdup(newreg->name);
5007 newreg->wasUsed = 1;
5009 r2 = setNextItem(pb->tregisters);
5012 r1 = setNextItem(registersInCallPath);
5015 /* Collisions have been resolved. Now free the registers in the call path */
5016 r1 = setFirstItem(registersInCallPath);
5018 if(r1->type != REG_STK) {
5019 newreg = pic14_regWithIdx(r1->rIdx);
5022 r1 = setNextItem(registersInCallPath);
5026 // MarkUsedRegisters(pb->registers);
5028 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5031 DFPRINTF((stderr,"returning regs\n"));
5033 DFPRINTF((stderr,"not returning regs\n"));
5035 DFPRINTF((stderr,"pBlock after register optim.\n"));
5036 pBlockStats(stderr,pb); // debug
5042 /*-----------------------------------------------------------------*/
5043 /* printCallTree - writes the call tree to a file */
5045 /*-----------------------------------------------------------------*/
5046 void pct2(FILE *of,pBlock *pb,int indent)
5050 // set *registersInCallPath = NULL;
5056 return; //recursion ?
5058 pc = setFirstItem(pb->function_entries);
5065 for(i=0;i<indent;i++) // Indentation
5068 if(pc->type == PC_FUNCTION)
5069 fprintf(of,"%s\n",PCF(pc)->fname);
5074 pc = setFirstItem(pb->function_calls);
5075 for( ; pc; pc = setNextItem(pb->function_calls)) {
5077 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5078 char *dest = get_op_from_instruction(PCI(pc));
5080 pcn = findFunction(dest);
5082 pct2(of,pcn->pb,indent+1);
5084 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5092 /*-----------------------------------------------------------------*/
5093 /* printCallTree - writes the call tree to a file */
5095 /*-----------------------------------------------------------------*/
5097 void printCallTree(FILE *of)
5109 fprintf(of, "\npBlock statistics\n");
5110 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5115 fprintf(of,"Call Tree\n");
5116 pbr = the_pFile->functions;
5120 if(!ispCodeFunction(pc))
5121 fprintf(of,"bug in call tree");
5124 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5126 while(pc->next && !ispCodeFunction(pc->next)) {
5128 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5129 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5137 fprintf(of,"\n**************\n\na better call tree\n");
5138 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5143 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5144 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5150 /*-----------------------------------------------------------------*/
5152 /*-----------------------------------------------------------------*/
5154 void InlineFunction(pBlock *pb)
5162 pc = setFirstItem(pb->function_calls);
5164 for( ; pc; pc = setNextItem(pb->function_calls)) {
5167 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5173 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5175 //fprintf(stderr,"Cool can inline:\n");
5176 //pcn->print(stderr,pcn);
5178 //fprintf(stderr,"recursive call Inline\n");
5179 InlineFunction(pcn->pb);
5180 //fprintf(stderr,"return from recursive call Inline\n");
5183 At this point, *pc points to a CALL mnemonic, and
5184 *pcn points to the function that is being called.
5186 To in-line this call, we need to remove the CALL
5187 and RETURN(s), and link the function pCode in with
5193 /* Remove the CALL */
5197 /* remove callee pBlock from the pBlock linked list */
5198 removepBlock(pcn->pb);
5206 /* Remove the Function pCode */
5207 pct = findNextInstruction(pcn->next);
5209 /* Link the function with the callee */
5210 pc->next = pcn->next;
5211 pcn->next->prev = pc;
5213 /* Convert the function name into a label */
5215 pbr = Safe_calloc(1,sizeof(pBranch));
5216 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5218 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5219 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5221 /* turn all of the return's except the last into goto's */
5222 /* check case for 2 instruction pBlocks */
5223 pce = findNextInstruction(pcn->next);
5225 pCode *pce_next = findNextInstruction(pce->next);
5227 if(pce_next == NULL) {
5228 /* found the last return */
5229 pCode *pc_call_next = findNextInstruction(pc_call->next);
5231 //fprintf(stderr,"found last return\n");
5232 //pce->print(stderr,pce);
5233 pce->prev->next = pc_call->next;
5234 pc_call->next->prev = pce->prev;
5235 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5245 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5251 /*-----------------------------------------------------------------*/
5253 /*-----------------------------------------------------------------*/
5255 void InlinepCode(void)
5264 if(!functionInlining)
5267 /* Loop through all of the function definitions and count the
5268 * number of times each one is called */
5269 //fprintf(stderr,"inlining %d\n",__LINE__);
5271 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5273 pc = setFirstItem(pb->function_calls);
5275 for( ; pc; pc = setNextItem(pb->function_calls)) {
5278 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5279 if(pcn && isPCF(pcn)) {
5280 PCF(pcn)->ncalled++;
5283 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5288 //fprintf(stderr,"inlining %d\n",__LINE__);
5290 /* Now, Loop through the function definitions again, but this
5291 * time inline those functions that have only been called once. */
5293 InlineFunction(the_pFile->pbHead);
5294 //fprintf(stderr,"inlining %d\n",__LINE__);
5296 for(pb = the_pFile->pbHead; pb; pb = pb->next)