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)
1209 static int initialized=0;
1215 initStack(0xfff, 8);
1216 init_pic(port->processor);
1218 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1219 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1220 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1221 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1222 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1223 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1225 pc_status.rIdx = IDX_STATUS;
1226 pc_fsr.rIdx = IDX_FSR;
1227 pc_indf.rIdx = IDX_INDF;
1228 pc_intcon.rIdx = IDX_INTCON;
1229 pc_pcl.rIdx = IDX_PCL;
1230 pc_pclath.rIdx = IDX_PCLATH;
1232 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1233 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1234 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1236 pc_kzero.rIdx = IDX_KZ;
1237 pc_wsave.rIdx = IDX_WSAVE;
1238 pc_ssave.rIdx = IDX_SSAVE;
1240 /* probably should put this in a separate initialization routine */
1241 pb_dead_pcodes = newpBlock();
1245 /*-----------------------------------------------------------------*/
1246 /* mnem2key - convert a pic mnemonic into a hash key */
1247 /* (BTW - this spreads the mnemonics quite well) */
1249 /*-----------------------------------------------------------------*/
1251 int mnem2key(char const *mnem)
1260 key += toupper(*mnem++) +1;
1264 return (key & 0x1f);
1268 void pic14initMnemonics(void)
1273 pCodeInstruction *pci;
1275 if(mnemonics_initialized)
1278 //FIXME - probably should NULL out the array before making the assignments
1279 //since we check the array contents below this initialization.
1281 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1282 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1283 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1284 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1285 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1286 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1287 pic14Mnemonics[POC_BCF] = &pciBCF;
1288 pic14Mnemonics[POC_BSF] = &pciBSF;
1289 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1290 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1291 pic14Mnemonics[POC_CALL] = &pciCALL;
1292 pic14Mnemonics[POC_COMF] = &pciCOMF;
1293 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1294 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1295 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1296 pic14Mnemonics[POC_DECF] = &pciDECF;
1297 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1298 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1299 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1300 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1301 pic14Mnemonics[POC_INCF] = &pciINCF;
1302 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1303 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1304 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1305 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1306 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1307 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1308 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1309 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1310 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1311 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1312 pic14Mnemonics[POC_NOP] = &pciNOP;
1313 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1314 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1315 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1316 pic14Mnemonics[POC_RLF] = &pciRLF;
1317 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1318 pic14Mnemonics[POC_RRF] = &pciRRF;
1319 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1320 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1321 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1322 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1323 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1324 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1325 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1326 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1327 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1328 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1330 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1331 if(pic14Mnemonics[i])
1332 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1333 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1336 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1337 pci = hTabNextItem(pic14MnemonicsHash, &key);
1340 mnemonics_initialized = 1;
1343 int getpCodePeepCommand(char *cmd);
1345 int getpCode(char *mnem,unsigned dest)
1348 pCodeInstruction *pci;
1349 int key = mnem2key(mnem);
1351 if(!mnemonics_initialized)
1352 pic14initMnemonics();
1354 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1358 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1359 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1363 pci = hTabNextItemWK (pic14MnemonicsHash);
1370 /*-----------------------------------------------------------------*
1371 * pic14initpCodePeepCommands
1373 *-----------------------------------------------------------------*/
1374 void pic14initpCodePeepCommands(void)
1382 hTabAddItem(&pic14pCodePeepCommandsHash,
1383 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1385 } while (peepCommands[i].cmd);
1387 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1390 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1391 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1396 /*-----------------------------------------------------------------
1399 *-----------------------------------------------------------------*/
1401 int getpCodePeepCommand(char *cmd)
1405 int key = mnem2key(cmd);
1408 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1411 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1412 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1416 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1423 char getpBlock_dbName(pBlock *pb)
1429 return pb->cmemmap->dbName;
1433 void pBlockConvert2ISR(pBlock *pb)
1444 /*-----------------------------------------------------------------*/
1445 /* movepBlock2Head - given the dbname of a pBlock, move all */
1446 /* instances to the front of the doubly linked */
1447 /* list of pBlocks */
1448 /*-----------------------------------------------------------------*/
1450 void movepBlock2Head(char dbName)
1454 pb = the_pFile->pbHead;
1458 if(getpBlock_dbName(pb) == dbName) {
1459 pBlock *pbn = pb->next;
1460 pb->next = the_pFile->pbHead;
1461 the_pFile->pbHead->prev = pb;
1462 the_pFile->pbHead = pb;
1465 pb->prev->next = pbn;
1467 // If the pBlock that we just moved was the last
1468 // one in the link of all of the pBlocks, then we
1469 // need to point the tail to the block just before
1470 // the one we moved.
1471 // Note: if pb->next is NULL, then pb must have
1472 // been the last pBlock in the chain.
1475 pbn->prev = pb->prev;
1477 the_pFile->pbTail = pb->prev;
1488 void copypCode(FILE *of, char dbName)
1492 if(!of || !the_pFile)
1495 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1496 if(getpBlock_dbName(pb) == dbName) {
1503 void pcode_test(void)
1506 DFPRINTF((stderr,"pcode is alive!\n"));
1516 /* create the file name */
1517 strcpy(buffer,srcFileName);
1518 strcat(buffer,".p");
1520 if( !(pFile = fopen(buffer, "w" ))) {
1521 werror(E_FILE_OPEN_ERR,buffer);
1525 fprintf(pFile,"pcode dump\n\n");
1527 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1528 fprintf(pFile,"\n\tNew pBlock\n\n");
1530 fprintf(pFile,"%s",pb->cmemmap->sname);
1532 fprintf(pFile,"internal pblock");
1534 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1535 printpBlock(pFile,pb);
1539 /*-----------------------------------------------------------------*/
1540 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1541 /* ister, RegCond will return the bit being referenced. */
1543 /* fixme - why not just OR in the pcop bit field */
1544 /*-----------------------------------------------------------------*/
1546 static int RegCond(pCodeOp *pcop)
1552 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1553 switch(PCORB(pcop)->bit) {
1567 /*-----------------------------------------------------------------*/
1568 /* newpCode - create and return a newly initialized pCode */
1570 /* fixme - rename this */
1572 /* The purpose of this routine is to create a new Instruction */
1573 /* pCode. This is called by gen.c while the assembly code is being */
1577 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1578 /* (note that the op is analogous to but not the */
1579 /* same thing as the opcode of the instruction.) */
1580 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1583 /* a pointer to the new malloc'd pCode is returned. */
1587 /*-----------------------------------------------------------------*/
1588 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1590 pCodeInstruction *pci ;
1592 if(!mnemonics_initialized)
1593 pic14initMnemonics();
1595 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1597 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1598 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1601 if(pci->inCond & PCC_EXAMINE_PCOP)
1602 pci->inCond |= RegCond(pcop);
1604 if(pci->outCond & PCC_EXAMINE_PCOP)
1605 pci->outCond |= RegCond(pcop);
1607 pci->pc.prev = pci->pc.next = NULL;
1608 return (pCode *)pci;
1611 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1617 /*-----------------------------------------------------------------*/
1618 /* newpCodeWild - create a "wild" as in wild card pCode */
1620 /* Wild pcodes are used during the peep hole optimizer to serve */
1621 /* as place holders for any instruction. When a snippet of code is */
1622 /* compared to a peep hole rule, the wild card opcode will match */
1623 /* any instruction. However, the optional operand and label are */
1624 /* additional qualifiers that must also be matched before the */
1625 /* line (of assembly code) is declared matched. Note that the */
1626 /* operand may be wild too. */
1628 /* Note, a wild instruction is specified just like a wild var: */
1629 /* %4 ; A wild instruction, */
1630 /* See the peeph.def file for additional examples */
1632 /*-----------------------------------------------------------------*/
1634 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1639 pcw = Safe_calloc(1,sizeof(pCodeWild));
1641 pcw->pci.pc.type = PC_WILD;
1642 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1643 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1644 pcw->pci.pc.pb = NULL;
1646 // pcw->pci.pc.analyze = genericAnalyze;
1647 pcw->pci.pc.destruct = genericDestruct;
1648 pcw->pci.pc.print = genericPrint;
1650 pcw->id = pCodeID; // this is the 'n' in %n
1651 pcw->operand = optional_operand;
1652 pcw->label = optional_label;
1654 pcw->mustBeBitSkipInst = 0;
1655 pcw->mustNotBeBitSkipInst = 0;
1656 pcw->invertBitSkipInst = 0;
1658 return ( (pCode *)pcw);
1662 /*-----------------------------------------------------------------*/
1663 /* newPcodeInlineP - create a new pCode from a char string */
1664 /*-----------------------------------------------------------------*/
1667 pCode *newpCodeInlineP(char *cP)
1672 pcc = Safe_calloc(1,sizeof(pCodeComment));
1674 pcc->pc.type = PC_INLINE;
1675 pcc->pc.prev = pcc->pc.next = NULL;
1676 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1679 // pcc->pc.analyze = genericAnalyze;
1680 pcc->pc.destruct = genericDestruct;
1681 pcc->pc.print = genericPrint;
1684 pcc->comment = Safe_strdup(cP);
1686 pcc->comment = NULL;
1688 return ( (pCode *)pcc);
1692 /*-----------------------------------------------------------------*/
1693 /* newPcodeCharP - create a new pCode from a char string */
1694 /*-----------------------------------------------------------------*/
1696 pCode *newpCodeCharP(char *cP)
1701 pcc = Safe_calloc(1,sizeof(pCodeComment));
1703 pcc->pc.type = PC_COMMENT;
1704 pcc->pc.prev = pcc->pc.next = NULL;
1705 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1708 // pcc->pc.analyze = genericAnalyze;
1709 pcc->pc.destruct = genericDestruct;
1710 pcc->pc.print = genericPrint;
1713 pcc->comment = Safe_strdup(cP);
1715 pcc->comment = NULL;
1717 return ( (pCode *)pcc);
1721 /*-----------------------------------------------------------------*/
1722 /* newpCodeFunction - */
1723 /*-----------------------------------------------------------------*/
1726 pCode *newpCodeFunction(char *mod,char *f)
1730 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1731 //_ALLOC(pcf,sizeof(pCodeFunction));
1733 pcf->pc.type = PC_FUNCTION;
1734 pcf->pc.prev = pcf->pc.next = NULL;
1735 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1738 // pcf->pc.analyze = genericAnalyze;
1739 pcf->pc.destruct = genericDestruct;
1740 pcf->pc.print = pCodePrintFunction;
1745 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1746 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1747 strcpy(pcf->modname,mod);
1749 pcf->modname = NULL;
1752 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1753 pcf->fname = Safe_calloc(1,strlen(f)+1);
1754 strcpy(pcf->fname,f);
1758 return ( (pCode *)pcf);
1762 /*-----------------------------------------------------------------*/
1764 /*-----------------------------------------------------------------*/
1766 void destructpCodeFlow(pCode *pc)
1768 if(!pc || !isPCFL(pc))
1772 free(PCFL(pc)->uses);
1780 pCode *newpCodeFlow(void )
1784 //_ALLOC(pcflow,sizeof(pCodeFlow));
1785 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1787 pcflow->pc.type = PC_FLOW;
1788 pcflow->pc.prev = pcflow->pc.next = NULL;
1789 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1790 pcflow->pc.pb = NULL;
1792 // pcflow->pc.analyze = genericAnalyze;
1793 pcflow->pc.destruct = destructpCodeFlow;
1794 pcflow->pc.print = genericPrint;
1796 pcflow->pc.seq = GpcFlowSeq++;
1799 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1801 pcflow->from = pcflow->to = NULL;
1803 pcflow->inCond = PCC_NONE;
1804 pcflow->outCond = PCC_NONE;
1806 pcflow->firstBank = -1;
1807 pcflow->lastBank = -1;
1809 pcflow->FromConflicts = 0;
1810 pcflow->ToConflicts = 0;
1814 pcflow->registers = newSet();
1816 return ( (pCode *)pcflow);
1820 /*-----------------------------------------------------------------*/
1821 /*-----------------------------------------------------------------*/
1822 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1824 pCodeFlowLink *pcflowLink;
1826 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1828 pcflowLink->pcflow = pcflow;
1829 pcflowLink->bank_conflict = 0;
1834 /*-----------------------------------------------------------------*/
1835 /* newpCodeCSource - create a new pCode Source Symbol */
1836 /*-----------------------------------------------------------------*/
1838 pCode *newpCodeCSource(int ln, char *f, char *l)
1843 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1845 pccs->pc.type = PC_CSOURCE;
1846 pccs->pc.prev = pccs->pc.next = NULL;
1849 pccs->pc.destruct = genericDestruct;
1850 pccs->pc.print = genericPrint;
1852 pccs->line_number = ln;
1854 pccs->line = Safe_strdup(l);
1859 pccs->file_name = Safe_strdup(f);
1861 pccs->file_name = NULL;
1863 return ( (pCode *)pccs);
1866 /*-----------------------------------------------------------------*/
1867 /* pCodeLabelDestruct - free memory used by a label. */
1868 /*-----------------------------------------------------------------*/
1869 static void pCodeLabelDestruct(pCode *pc)
1875 if((pc->type == PC_LABEL) && PCL(pc)->label)
1876 free(PCL(pc)->label);
1882 pCode *newpCodeLabel(char *name, int key)
1888 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1890 pcl->pc.type = PC_LABEL;
1891 pcl->pc.prev = pcl->pc.next = NULL;
1892 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1895 // pcl->pc.analyze = genericAnalyze;
1896 pcl->pc.destruct = pCodeLabelDestruct;
1897 pcl->pc.print = pCodePrintLabel;
1903 sprintf(s,"_%05d_DS_",key);
1908 pcl->label = Safe_strdup(s);
1911 return ( (pCode *)pcl);
1916 /*-----------------------------------------------------------------*/
1917 /* newpBlock - create and return a pointer to a new pBlock */
1918 /*-----------------------------------------------------------------*/
1919 pBlock *newpBlock(void)
1924 PpB = Safe_calloc(1,sizeof(pBlock) );
1925 PpB->next = PpB->prev = NULL;
1927 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1928 PpB->tregisters = NULL;
1930 PpB->FlowTree = NULL;
1936 /*-----------------------------------------------------------------*/
1937 /* newpCodeChain - create a new chain of pCodes */
1938 /*-----------------------------------------------------------------*
1940 * This function will create a new pBlock and the pointer to the
1941 * pCode that is passed in will be the first pCode in the block.
1942 *-----------------------------------------------------------------*/
1945 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1948 pBlock *pB = newpBlock();
1950 pB->pcHead = pB->pcTail = pc;
1957 /*-----------------------------------------------------------------*/
1958 /* newpCodeOpLabel - Create a new label given the key */
1959 /* Note, a negative key means that the label is part of wild card */
1960 /* (and hence a wild card label) used in the pCodePeep */
1961 /* optimizations). */
1962 /*-----------------------------------------------------------------*/
1964 pCodeOp *newpCodeOpLabel(char *name, int key)
1967 static int label_key=-1;
1971 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1972 pcop->type = PO_LABEL;
1977 sprintf(s=buffer,"_%05d_DS_",key);
1979 s = name, key = label_key--;
1982 pcop->name = Safe_strdup(s);
1984 ((pCodeOpLabel *)pcop)->key = key;
1989 /*-----------------------------------------------------------------*/
1990 /*-----------------------------------------------------------------*/
1991 pCodeOp *newpCodeOpLit(int lit)
1997 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1998 pcop->type = PO_LITERAL;
2002 sprintf(s,"0x%02x",lit);
2004 pcop->name = Safe_strdup(s);
2007 ((pCodeOpLit *)pcop)->lit = lit;
2012 /*-----------------------------------------------------------------*/
2013 /*-----------------------------------------------------------------*/
2014 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2018 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2019 pcop->type = PO_IMMEDIATE;
2021 regs *r = dirregWithName(name);
2022 pcop->name = Safe_strdup(name);
2025 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2026 PCOI(pcop)->rIdx = r->rIdx;
2028 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2029 PCOI(pcop)->rIdx = -1;
2031 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2036 PCOI(pcop)->index = index;
2037 PCOI(pcop)->offset = offset;
2038 PCOI(pcop)->_const = code_space;
2043 /*-----------------------------------------------------------------*/
2044 /*-----------------------------------------------------------------*/
2045 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2051 if(!pcwb || !subtype) {
2052 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2056 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2057 pcop->type = PO_WILD;
2058 sprintf(s,"%%%d",id);
2059 pcop->name = Safe_strdup(s);
2061 PCOW(pcop)->id = id;
2062 PCOW(pcop)->pcwb = pcwb;
2063 PCOW(pcop)->subtype = subtype;
2064 PCOW(pcop)->matched = NULL;
2069 /*-----------------------------------------------------------------*/
2070 /*-----------------------------------------------------------------*/
2071 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2075 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2076 pcop->type = PO_GPR_BIT;
2078 pcop->name = Safe_strdup(s);
2082 PCORB(pcop)->bit = bit;
2083 PCORB(pcop)->inBitSpace = inBitSpace;
2088 /*-----------------------------------------------------------------*
2089 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2091 * If rIdx >=0 then a specific register from the set of registers
2092 * will be selected. If rIdx <0, then a new register will be searched
2094 *-----------------------------------------------------------------*/
2096 pCodeOp *newpCodeOpReg(int rIdx)
2100 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2105 PCOR(pcop)->rIdx = rIdx;
2106 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2108 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2111 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2112 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2115 pcop->type = PCOR(pcop)->r->pc_type;
2120 pCodeOp *newpCodeOpRegFromStr(char *name)
2124 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2125 PCOR(pcop)->r = allocRegByName(name, 1);
2126 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2127 pcop->type = PCOR(pcop)->r->pc_type;
2128 pcop->name = PCOR(pcop)->r->name;
2133 /*-----------------------------------------------------------------*/
2134 /*-----------------------------------------------------------------*/
2136 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2143 pcop = newpCodeOpBit(name, -1,0);
2147 pcop = newpCodeOpLit(-1);
2151 pcop = newpCodeOpLabel(NULL,-1);
2154 pcop = newpCodeOpReg(-1);
2158 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2161 pcop->name = Safe_strdup(name);
2169 /*-----------------------------------------------------------------*/
2170 /*-----------------------------------------------------------------*/
2171 void pCodeConstString(char *name, char *value)
2175 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2180 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2184 sprintf(buffer,"; %s = %s",name,value);
2186 addpCode2pBlock(pb,newpCodeCharP(buffer));
2187 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2190 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2196 /*-----------------------------------------------------------------*/
2197 /*-----------------------------------------------------------------*/
2198 void pCodeReadCodeTable(void)
2202 fprintf(stderr, " %s\n",__FUNCTION__);
2204 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2208 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2209 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2210 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2211 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2213 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2214 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2215 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2216 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2221 /*-----------------------------------------------------------------*/
2222 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2223 /*-----------------------------------------------------------------*/
2224 void addpCode2pBlock(pBlock *pb, pCode *pc)
2227 /* If this is the first pcode to be added to a block that
2228 * was initialized with a NULL pcode, then go ahead and
2229 * make this pcode the head and tail */
2230 pb->pcHead = pb->pcTail = pc;
2232 pb->pcTail->next = pc;
2233 pc->prev = pb->pcTail;
2240 /*-----------------------------------------------------------------*/
2241 /* addpBlock - place a pBlock into the pFile */
2242 /*-----------------------------------------------------------------*/
2243 void addpBlock(pBlock *pb)
2245 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2248 /* First time called, we'll pass through here. */
2249 //_ALLOC(the_pFile,sizeof(pFile));
2250 the_pFile = Safe_calloc(1,sizeof(pFile));
2251 the_pFile->pbHead = the_pFile->pbTail = pb;
2252 the_pFile->functions = NULL;
2256 the_pFile->pbTail->next = pb;
2257 pb->prev = the_pFile->pbTail;
2259 the_pFile->pbTail = pb;
2262 /*-----------------------------------------------------------------*/
2263 /* removepBlock - remove a pBlock from the pFile */
2264 /*-----------------------------------------------------------------*/
2265 void removepBlock(pBlock *pb)
2273 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2275 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2278 if(pbs == the_pFile->pbHead)
2279 the_pFile->pbHead = pbs->next;
2281 if (pbs == the_pFile->pbTail)
2282 the_pFile->pbTail = pbs->prev;
2285 pbs->next->prev = pbs->prev;
2288 pbs->prev->next = pbs->next;
2295 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2299 /*-----------------------------------------------------------------*/
2300 /* printpCode - write the contents of a pCode to a file */
2301 /*-----------------------------------------------------------------*/
2302 void printpCode(FILE *of, pCode *pc)
2313 fprintf(of,"warning - unable to print pCode\n");
2316 /*-----------------------------------------------------------------*/
2317 /* printpBlock - write the contents of a pBlock to a file */
2318 /*-----------------------------------------------------------------*/
2319 void printpBlock(FILE *of, pBlock *pb)
2329 for(pc = pb->pcHead; pc; pc = pc->next)
2334 /*-----------------------------------------------------------------*/
2336 /* pCode processing */
2340 /*-----------------------------------------------------------------*/
2342 void unlinkpCode(pCode *pc)
2348 fprintf(stderr,"Unlinking: ");
2349 printpCode(stderr, pc);
2352 pc->prev->next = pc->next;
2354 pc->next->prev = pc->prev;
2356 pc->prev = pc->next = NULL;
2360 /*-----------------------------------------------------------------*/
2361 /*-----------------------------------------------------------------*/
2363 static void genericDestruct(pCode *pc)
2369 /* For instructions, tell the register (if there's one used)
2370 * that it's no longer needed */
2371 regs *reg = getRegFromInstruction(pc);
2373 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2376 /* Instead of deleting the memory used by this pCode, mark
2377 * the object as bad so that if there's a pointer to this pCode
2378 * dangling around somewhere then (hopefully) when the type is
2379 * checked we'll catch it.
2384 addpCode2pBlock(pb_dead_pcodes, pc);
2391 /*-----------------------------------------------------------------*/
2392 /*-----------------------------------------------------------------*/
2393 void pBlockRegs(FILE *of, pBlock *pb)
2398 r = setFirstItem(pb->tregisters);
2400 r = setNextItem(pb->tregisters);
2405 /*-----------------------------------------------------------------*/
2406 /*-----------------------------------------------------------------*/
2407 char *get_op(pCodeOp *pcop,char *buffer, int size)
2412 int use_buffer = 1; // copy the string to the passed buffer pointer
2417 use_buffer = 0; // Don't bother copying the string to the buffer.
2421 switch(pcop->type) {
2425 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2428 return PCOR(pcop)->r->name;
2431 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2434 SAFE_snprintf(&buffer,&size,"%s",r->name);
2444 if(PCOI(pcop)->_const) {
2446 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2447 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2450 8 * PCOI(pcop)->offset );
2452 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2455 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2456 SAFE_snprintf(&s,&size,"(%s + %d)",
2458 PCOI(pcop)->index );
2460 SAFE_snprintf(&s,&size,"%s",pcop->name);
2467 //size = sizeof(buffer);
2468 if( PCOR(pcop)->instance) {
2469 SAFE_snprintf(&s,&size,"(%s + %d)",
2471 PCOR(pcop)->instance );
2472 //fprintf(stderr,"PO_DIR %s\n",buffer);
2474 SAFE_snprintf(&s,&size,"%s",pcop->name);
2480 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2489 return "NO operand";
2493 /*-----------------------------------------------------------------*/
2494 /*-----------------------------------------------------------------*/
2495 static char *get_op_from_instruction( pCodeInstruction *pcc)
2499 return get_op(pcc->pcop,NULL,0);
2501 return ("ERROR Null: "__FUNCTION__);
2505 /*-----------------------------------------------------------------*/
2506 /*-----------------------------------------------------------------*/
2507 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2510 fprintf(of,"pcodeopprint- not implemented\n");
2513 /*-----------------------------------------------------------------*/
2514 /*-----------------------------------------------------------------*/
2515 char *pCode2str(char *str, int size, pCode *pc)
2523 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2525 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2527 if(PCI(pc)->isBitInst) {
2528 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2529 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2530 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2531 PCI(pc)->pcop->name ,
2532 PCI(pc)->pcop->name );
2534 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2535 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2536 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2537 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2539 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2540 //PCI(pc)->pcop->t.bit );
2543 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2544 if( PCI(pc)->num_ops == 2)
2545 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2547 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2550 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2552 if( PCI(pc)->num_ops == 2)
2553 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2561 /* assuming that comment ends with a \n */
2562 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2566 /* assuming that inline code ends with a \n */
2567 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2571 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2574 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2577 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2580 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2583 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2587 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2594 /*-----------------------------------------------------------------*/
2595 /* genericPrint - the contents of a pCode to a file */
2596 /*-----------------------------------------------------------------*/
2597 static void genericPrint(FILE *of, pCode *pc)
2605 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2609 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2613 // If the opcode has a label, print that first
2615 pBranch *pbl = PCI(pc)->label;
2616 while(pbl && pbl->pc) {
2617 if(pbl->pc->type == PC_LABEL)
2618 pCodePrintLabel(of, pbl->pc);
2624 genericPrint(of,PCODE(PCI(pc)->cline));
2629 pCode2str(str, 256, pc);
2631 fprintf(of,"%s",str);
2634 fprintf(of, "\t;key=%03x",pc->seq);
2636 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2640 pBranch *dpb = pc->to; // debug
2642 switch ( dpb->pc->type) {
2644 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2647 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2650 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2653 fprintf(of, "\t;flow");
2667 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2668 if(PCW(pc)->pci.label)
2669 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2671 if(PCW(pc)->operand) {
2672 fprintf(of,";\toperand ");
2673 pCodeOpPrint(of,PCW(pc)->operand );
2678 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2682 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2686 fprintf(of,"unknown pCode type %d\n",pc->type);
2691 /*-----------------------------------------------------------------*/
2692 /* pCodePrintFunction - prints function begin/end */
2693 /*-----------------------------------------------------------------*/
2695 static void pCodePrintFunction(FILE *of, pCode *pc)
2701 if( ((pCodeFunction *)pc)->modname)
2702 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2704 if(PCF(pc)->fname) {
2705 pBranch *exits = PCF(pc)->to;
2707 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2710 exits = exits->next;
2713 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2716 if((PCF(pc)->from &&
2717 PCF(pc)->from->pc->type == PC_FUNCTION &&
2718 PCF(PCF(pc)->from->pc)->fname) )
2719 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2721 fprintf(of,"; exit point [can't find entry point]\n");
2724 /*-----------------------------------------------------------------*/
2725 /* pCodePrintLabel - prints label */
2726 /*-----------------------------------------------------------------*/
2728 static void pCodePrintLabel(FILE *of, pCode *pc)
2735 fprintf(of,"%s\n",PCL(pc)->label);
2736 else if (PCL(pc)->key >=0)
2737 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2739 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2742 /*-----------------------------------------------------------------*/
2743 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2744 /* remove it if it is found. */
2745 /*-----------------------------------------------------------------*/
2746 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2753 if(pcl->type == PC_OPCODE)
2754 b = PCI(pcl)->label;
2756 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2761 //fprintf (stderr, "%s \n",__FUNCTION__);
2762 //pcl->print(stderr,pcl);
2763 //pc->print(stderr,pc);
2766 //fprintf (stderr, "found label\n");
2770 bprev->next = b->next; /* Not first pCode in chain */
2774 PCI(pcl)->label = b->next; /* First pCode in chain */
2777 return; /* A label can't occur more than once */
2785 /*-----------------------------------------------------------------*/
2786 /*-----------------------------------------------------------------*/
2787 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2806 /*-----------------------------------------------------------------*/
2807 /* pBranchLink - given two pcodes, this function will link them */
2808 /* together through their pBranches */
2809 /*-----------------------------------------------------------------*/
2810 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2814 // Declare a new branch object for the 'from' pCode.
2816 //_ALLOC(b,sizeof(pBranch));
2817 b = Safe_calloc(1,sizeof(pBranch));
2818 b->pc = PCODE(t); // The link to the 'to' pCode.
2821 f->to = pBranchAppend(f->to,b);
2823 // Now do the same for the 'to' pCode.
2825 //_ALLOC(b,sizeof(pBranch));
2826 b = Safe_calloc(1,sizeof(pBranch));
2830 t->from = pBranchAppend(t->from,b);
2835 /*-----------------------------------------------------------------*/
2836 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2838 /*-----------------------------------------------------------------*/
2839 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2852 /*-----------------------------------------------------------------*/
2853 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2854 /*-----------------------------------------------------------------*/
2855 static void pCodeUnlink(pCode *pc)
2860 if(!pc->prev || !pc->next) {
2861 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2865 /* first remove the pCode from the chain */
2866 pc->prev->next = pc->next;
2867 pc->next->prev = pc->prev;
2869 /* Now for the hard part... */
2871 /* Remove the branches */
2875 pc1 = pb1->pc; /* Get the pCode that branches to the
2876 * one we're unlinking */
2878 /* search for the link back to this pCode (the one we're
2880 if(pb2 = pBranchFind(pc1->to,pc)) {
2881 pb2->pc = pc->to->pc; // make the replacement
2883 /* if the pCode we're unlinking contains multiple 'to'
2884 * branches (e.g. this a skip instruction) then we need
2885 * to copy these extra branches to the chain. */
2887 pBranchAppend(pb2, pc->to->next);
2896 /*-----------------------------------------------------------------*/
2897 /*-----------------------------------------------------------------*/
2899 static void genericAnalyze(pCode *pc)
2909 // Go through the pCodes that are in pCode chain and link
2910 // them together through the pBranches. Note, the pCodes
2911 // are linked together as a contiguous stream like the
2912 // assembly source code lines. The linking here mimics this
2913 // except that comments are not linked in.
2915 pCode *npc = pc->next;
2917 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2918 pBranchLink(pc,npc);
2923 /* reached the end of the pcode chain without finding
2924 * an instruction we could link to. */
2928 fprintf(stderr,"analyze PC_FLOW\n");
2932 fprintf(stderr,,";A bad pCode is being used\n");
2938 /*-----------------------------------------------------------------*/
2939 /*-----------------------------------------------------------------*/
2940 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2944 if(pc->type == PC_LABEL) {
2945 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2948 if(pc->type == PC_OPCODE) {
2949 pbr = PCI(pc)->label;
2951 if(pbr->pc->type == PC_LABEL) {
2952 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2962 /*-----------------------------------------------------------------*/
2963 /*-----------------------------------------------------------------*/
2964 int checkLabel(pCode *pc)
2968 if(pc && isPCI(pc)) {
2969 pbr = PCI(pc)->label;
2971 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2981 /*-----------------------------------------------------------------*/
2982 /* findLabelinpBlock - Search the pCode for a particular label */
2983 /*-----------------------------------------------------------------*/
2984 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2991 for(pc = pb->pcHead; pc; pc = pc->next)
2992 if(compareLabel(pc,pcop_label))
2998 /*-----------------------------------------------------------------*/
2999 /* findLabel - Search the pCode for a particular label */
3000 /*-----------------------------------------------------------------*/
3001 pCode * findLabel(pCodeOpLabel *pcop_label)
3009 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3010 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3014 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3018 /*-----------------------------------------------------------------*/
3019 /* findNextpCode - given a pCode, find the next of type 'pct' */
3020 /* in the linked list */
3021 /*-----------------------------------------------------------------*/
3022 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3035 /*-----------------------------------------------------------------*/
3036 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3037 /* in the linked list */
3038 /*-----------------------------------------------------------------*/
3039 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3051 /*-----------------------------------------------------------------*/
3052 /* findNextInstruction - given a pCode, find the next instruction */
3053 /* in the linked list */
3054 /*-----------------------------------------------------------------*/
3055 pCode * findNextInstruction(pCode *pci)
3060 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3064 fprintf(stderr,"findNextInstruction: ");
3065 printpCode(stderr, pc);
3070 //fprintf(stderr,"Couldn't find instruction\n");
3074 /*-----------------------------------------------------------------*/
3075 /* findNextInstruction - given a pCode, find the next instruction */
3076 /* in the linked list */
3077 /*-----------------------------------------------------------------*/
3078 pCode * findPrevInstruction(pCode *pci)
3080 return findPrevpCode(pci, PC_OPCODE);
3083 /*-----------------------------------------------------------------*/
3084 /* findFunctionEnd - given a pCode find the end of the function */
3085 /* that contains it */
3086 /*-----------------------------------------------------------------*/
3087 pCode * findFunctionEnd(pCode *pc)
3091 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3097 fprintf(stderr,"Couldn't find function end\n");
3102 /*-----------------------------------------------------------------*/
3103 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3104 /* instruction with which it is associated. */
3105 /*-----------------------------------------------------------------*/
3106 static void AnalyzeLabel(pCode *pc)
3115 static void AnalyzeGOTO(pCode *pc)
3118 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3122 static void AnalyzeSKIP(pCode *pc)
3125 pBranchLink(pc,findNextInstruction(pc->next));
3126 pBranchLink(pc,findNextInstruction(pc->next->next));
3130 static void AnalyzeRETURN(pCode *pc)
3133 // branch_link(pc,findFunctionEnd(pc->next));
3139 /*-----------------------------------------------------------------*/
3140 /*-----------------------------------------------------------------*/
3141 regs * getRegFromInstruction(pCode *pc)
3147 PCI(pc)->num_ops == 0 )
3150 switch(PCI(pc)->pcop->type) {
3153 return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3157 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3158 return PCOR(PCI(pc)->pcop)->r;
3161 if(PCOI(PCI(pc)->pcop)->r)
3162 return (PCOI(PCI(pc)->pcop)->r);
3164 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3165 return dirregWithName(PCI(pc)->pcop->name);
3166 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3169 return PCOR(PCI(pc)->pcop)->r;
3172 //fprintf(stderr, "getRegFromInstruction - dir\n");
3173 return PCOR(PCI(pc)->pcop)->r;
3175 //fprintf(stderr, "getRegFromInstruction - literal\n");
3179 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3180 //genericPrint(stderr, pc);
3188 /*-----------------------------------------------------------------*/
3189 /*-----------------------------------------------------------------*/
3191 void AnalyzepBlock(pBlock *pb)
3198 /* Find all of the registers used in this pBlock
3199 * by looking at each instruction and examining it's
3202 for(pc = pb->pcHead; pc; pc = pc->next) {
3204 /* Is this an instruction with operands? */
3205 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3207 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3209 /* Loop through all of the registers declared so far in
3210 this block and see if we find this one there */
3212 regs *r = setFirstItem(pb->tregisters);
3215 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3216 PCOR(PCI(pc)->pcop)->r = r;
3219 r = setNextItem(pb->tregisters);
3223 /* register wasn't found */
3224 //r = Safe_calloc(1, sizeof(regs));
3225 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3226 //addSet(&pb->tregisters, r);
3227 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3228 //PCOR(PCI(pc)->pcop)->r = r;
3229 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3231 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3234 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3235 if(PCOR(PCI(pc)->pcop)->r) {
3236 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3237 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3239 if(PCI(pc)->pcop->name)
3240 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3242 fprintf(stderr,"ERROR: NULL register\n");
3251 /*-----------------------------------------------------------------*/
3253 /*-----------------------------------------------------------------*/
3254 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3256 void InsertpFlow(pCode *pc, pCode **pflow)
3258 PCFL(*pflow)->end = pc;
3260 if(!pc || !pc->next)
3263 *pflow = newpCodeFlow();
3264 pCodeInsertAfter(pc, *pflow);
3267 /*-----------------------------------------------------------------*/
3268 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3269 /* the flow blocks. */
3271 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3272 * point the instruction flow changes.
3274 /*-----------------------------------------------------------------*/
3275 void BuildFlow(pBlock *pb)
3278 pCode *last_pci=NULL;
3285 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3286 /* Insert a pCodeFlow object at the beginning of a pBlock */
3288 pflow = newpCodeFlow(); /* Create a new Flow object */
3289 pflow->next = pb->pcHead; /* Make the current head the next object */
3290 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3291 pb->pcHead = pflow; /* Make the Flow object the head */
3294 for( pc = findNextInstruction(pb->pcHead);
3296 pc=findNextInstruction(pc)) {
3299 PCI(pc)->pcflow = PCFL(pflow);
3301 //fprintf(stderr," build: ");
3302 //pflow->print(stderr,pflow);
3304 if( PCI(pc)->isSkip) {
3306 /* The two instructions immediately following this one
3307 * mark the beginning of a new flow segment */
3309 while(pc && PCI(pc)->isSkip) {
3311 PCI(pc)->pcflow = PCFL(pflow);
3315 InsertpFlow(pc, &pflow);
3316 pc=findNextInstruction(pc->next);
3324 PCI(pc)->pcflow = PCFL(pflow);
3326 InsertpFlow(pc, &pflow);
3328 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3330 InsertpFlow(pc, &pflow);
3333 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3335 /* This instruction marks the beginning of a
3336 * new flow segment */
3340 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3342 PCI(pc)->pcflow = PCFL(pflow);
3349 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3350 PCFL(pflow)->end = pb->pcTail;
3353 /*-------------------------------------------------------------------*/
3354 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3355 /* the flow blocks. */
3357 * unBuildFlow removes pCodeFlow objects from a pCode chain
3359 /*-----------------------------------------------------------------*/
3360 void unBuildFlow(pBlock *pb)
3369 pCode *pcn = pc->next;
3373 PCI(pc)->pcflow = NULL;
3375 } else if(isPCFL(pc)) {
3385 /*-----------------------------------------------------------------*/
3386 /*-----------------------------------------------------------------*/
3387 void dumpCond(int cond)
3390 static char *pcc_str[] = {
3404 int ncond = sizeof(pcc_str) / sizeof(char *);
3407 fprintf(stderr, "0x%04X\n",cond);
3409 for(i=0,j=1; i<ncond; i++, j<<=1)
3411 fprintf(stderr, " %s\n",pcc_str[i]);
3415 /*-----------------------------------------------------------------*/
3416 /*-----------------------------------------------------------------*/
3417 void FlowStats(pCodeFlow *pcflow)
3425 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3427 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3430 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3435 fprintf(stderr, " FlowStats inCond: ");
3436 dumpCond(pcflow->inCond);
3437 fprintf(stderr, " FlowStats outCond: ");
3438 dumpCond(pcflow->outCond);
3442 /*-----------------------------------------------------------------*
3443 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3444 * if it affects the banking bits.
3446 * return: -1 == Banking bits are unaffected by this pCode.
3448 * return: > 0 == Banking bits are affected.
3450 * If the banking bits are affected, then the returned value describes
3451 * which bits are affected and how they're affected. The lower half
3452 * of the integer maps to the bits that are affected, the upper half
3453 * to whether they're set or cleared.
3455 *-----------------------------------------------------------------*/
3456 #define SET_BANK_BIT (1 << 16)
3457 #define CLR_BANK_BIT 0
3459 int isBankInstruction(pCode *pc)
3467 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3469 /* Check to see if the register banks are changing */
3470 if(PCI(pc)->isModReg) {
3472 pCodeOp *pcop = PCI(pc)->pcop;
3473 switch(PCI(pc)->op) {
3476 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3477 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3478 return SET_BANK_BIT | PIC_RP0_BIT;
3481 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3482 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3483 return CLR_BANK_BIT | PIC_RP0_BIT;
3488 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3489 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3490 return CLR_BANK_BIT | PIC_RP1_BIT;
3492 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3493 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3494 return CLR_BANK_BIT | PIC_RP1_BIT;
3498 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3499 //genericPrint(stderr, pc);
3510 /*-----------------------------------------------------------------*/
3511 /*-----------------------------------------------------------------*/
3512 void FillFlow(pCodeFlow *pcflow)
3521 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3523 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3526 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3533 isBankInstruction(pc);
3535 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3539 fprintf(stderr, " FillFlow - Bad end of flow\n");
3541 fprintf(stderr, " FillFlow - Ending flow with\n ");
3542 pc->print(stderr,pc);
3545 fprintf(stderr, " FillFlow inCond: ");
3546 dumpCond(pcflow->inCond);
3547 fprintf(stderr, " FillFlow outCond: ");
3548 dumpCond(pcflow->outCond);
3552 /*-----------------------------------------------------------------*/
3553 /*-----------------------------------------------------------------*/
3554 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3556 pCodeFlowLink *fromLink, *toLink;
3558 if(!from || !to || !to->pcflow || !from->pcflow)
3561 fromLink = newpCodeFlowLink(from->pcflow);
3562 toLink = newpCodeFlowLink(to->pcflow);
3564 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3565 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3569 /*-----------------------------------------------------------------*/
3570 /*-----------------------------------------------------------------*/
3571 void LinkFlow(pBlock *pb)
3577 //fprintf(stderr,"linkflow \n");
3579 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3581 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3584 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3586 //fprintf(stderr," link: ");
3587 //pcflow->print(stderr,pcflow);
3589 //FillFlow(PCFL(pcflow));
3591 pc = PCFL(pcflow)->end;
3593 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3594 if(isPCI_SKIP(pc)) {
3595 //fprintf(stderr, "ends with skip\n");
3596 //pc->print(stderr,pc);
3597 pct=findNextInstruction(pc->next);
3598 LinkFlow_pCode(PCI(pc),PCI(pct));
3599 pct=findNextInstruction(pct->next);
3600 LinkFlow_pCode(PCI(pc),PCI(pct));
3604 if(isPCI_BRANCH(pc)) {
3605 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3607 //fprintf(stderr, "ends with branch\n ");
3608 //pc->print(stderr,pc);
3610 if(!(pcol && isPCOLAB(pcol))) {
3611 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3612 pc->print(stderr,pc);
3613 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3618 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3619 LinkFlow_pCode(PCI(pc),PCI(pct));
3621 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3627 //fprintf(stderr, "ends with non-branching instruction:\n");
3628 //pc->print(stderr,pc);
3630 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3636 //fprintf(stderr, "ends with unknown\n");
3637 //pc->print(stderr,pc);
3641 //fprintf(stderr, "ends with nothing: ERROR\n");
3646 /*-----------------------------------------------------------------*/
3647 /*-----------------------------------------------------------------*/
3648 int isPCinFlow(pCode *pc, pCode *pcflow)
3654 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3657 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3663 /*-----------------------------------------------------------------*/
3664 /*-----------------------------------------------------------------*/
3665 void BanksUsedFlow2(pCode *pcflow)
3674 if(!isPCFL(pcflow)) {
3675 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3679 pc = findNextInstruction(pcflow->next);
3681 PCFL(pcflow)->lastBank = -1;
3683 while(isPCinFlow(pc,pcflow)) {
3685 int bank_selected = isBankInstruction(pc);
3687 //if(PCI(pc)->pcflow)
3688 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3690 if(bank_selected > 0) {
3691 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3693 /* This instruction is modifying banking bits before accessing registers */
3695 PCFL(pcflow)->firstBank = -1;
3697 if(PCFL(pcflow)->lastBank == -1)
3698 PCFL(pcflow)->lastBank = 0;
3700 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3701 if(bank_selected & SET_BANK_BIT)
3702 PCFL(pcflow)->lastBank |= bank;
3706 reg = getRegFromInstruction(pc);
3708 if(reg && !isREGinBank(reg, bank)) {
3709 int allbanks = REGallBanks(reg);
3711 PCFL(pcflow)->firstBank = allbanks;
3713 PCFL(pcflow)->lastBank = allbanks;
3720 pc = findNextInstruction(pc->next);
3723 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3724 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3729 /*-----------------------------------------------------------------*/
3730 /*-----------------------------------------------------------------*/
3731 void BanksUsedFlow(pBlock *pb)
3736 //pb->pcHead->print(stderr, pb->pcHead);
3738 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3739 //pcflow->print(stderr,pcflow);
3741 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3743 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3745 BanksUsedFlow2(pcflow);
3751 /*-----------------------------------------------------------------*/
3752 /*-----------------------------------------------------------------*/
3753 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3761 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3763 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3764 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3766 pCodeInsertAfter(pc->prev, new_pc);
3768 /* Move the label, if there is one */
3770 if(PCI(pc)->label) {
3771 PCI(new_pc)->label = PCI(pc)->label;
3772 PCI(pc)->label = NULL;
3775 /* The new instruction has the same pcflow block */
3776 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3779 /*-----------------------------------------------------------------*/
3780 /*-----------------------------------------------------------------*/
3781 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3792 pc = findNextInstruction(pcfl->pc.next);
3794 while(isPCinFlow(pc,PCODE(pcfl))) {
3797 reg = getRegFromInstruction(pc);
3800 fprintf(stderr, " %s ",reg->name);
3801 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3806 if(reg && REG_BANK(reg)!=cur_bank) {
3807 /* Examine the instruction before this one to make sure it is
3808 * not a skip type instruction */
3809 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3810 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3811 int b = cur_bank ^ REG_BANK(reg);
3813 //fprintf(stderr, "Cool! can switch banks\n");
3814 cur_bank = REG_BANK(reg);
3819 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3822 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3823 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3827 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3828 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3830 insertBankSwitch(pc, -1, -1);
3833 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3834 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3835 pCodeInsertAfter(pc->prev, new_pc);
3836 if(PCI(pc)->label) {
3837 PCI(new_pc)->label = PCI(pc)->label;
3838 PCI(pc)->label = NULL;
3842 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3843 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3844 pCodeInsertAfter(pc, new_pc);
3850 //fprintf(stderr, "Bummer can't switch banks\n");
3856 pc = findNextInstruction(pc->next);
3860 if(pcprev && cur_bank) {
3861 /* Brute force - make sure that we point to bank 0 at the
3862 * end of each flow block */
3863 new_pc = newpCode(POC_BCF,
3864 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3865 pCodeInsertAfter(pcprev, new_pc);
3871 /*-----------------------------------------------------------------*/
3872 /*int compareBankFlow - compare the banking requirements between */
3874 /*-----------------------------------------------------------------*/
3875 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3878 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3881 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3884 if(pcflow->firstBank == -1)
3888 if(pcflowLink->pcflow->firstBank == -1) {
3889 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3890 pcflowLink->pcflow->to :
3891 pcflowLink->pcflow->from);
3892 return compareBankFlow(pcflow, pctl, toORfrom);
3896 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3899 pcflowLink->bank_conflict++;
3900 pcflowLink->pcflow->FromConflicts++;
3901 pcflow->ToConflicts++;
3904 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3907 pcflowLink->bank_conflict++;
3908 pcflowLink->pcflow->ToConflicts++;
3909 pcflow->FromConflicts++;
3913 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3914 pcflowLink->pcflow->pc.seq,
3915 pcflowLink->pcflow->FromConflicts,
3916 pcflowLink->pcflow->ToConflicts);
3921 /*-----------------------------------------------------------------*/
3922 /*-----------------------------------------------------------------*/
3923 void FixBankFlow(pBlock *pb)
3927 pCodeFlowLink *pcfl;
3929 pCode *pcflow_max_To=NULL;
3930 pCode *pcflow_max_From=NULL;
3931 int max_ToConflicts=0;
3932 int max_FromConflicts=0;
3934 //fprintf(stderr,"Fix Bank flow \n");
3935 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3939 First loop through all of the flow objects in this pcode block
3940 and fix the ones that have banking conflicts between the
3944 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3946 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3948 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3950 if(!isPCFL(pcflow)) {
3951 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3955 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3956 PCFL(pcflow)->firstBank >= 0 &&
3957 PCFL(pcflow)->lastBank >= 0 ) {
3959 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3960 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3962 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3963 BanksUsedFlow2(pcflow);
3968 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3970 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3972 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3977 if(!isPCFL(pcflow)) {
3978 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3982 PCFL(pcflow)->FromConflicts = 0;
3983 PCFL(pcflow)->ToConflicts = 0;
3988 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3989 pcfl = setFirstItem(PCFL(pcflow)->from);
3992 pc = PCODE(pcfl->pcflow);
3995 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3996 pc->print(stderr,pc);
3999 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4002 pcfl=setNextItem(PCFL(pcflow)->from);
4005 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4006 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4008 FixRegisterBankingInFlow(PCFL(pcflow),0);
4009 BanksUsedFlow2(pcflow);
4011 continue; /* Don't need to check the flow from here - it's already been fixed */
4018 pcfl = setFirstItem(PCFL(pcflow)->to);
4021 pc = PCODE(pcfl->pcflow);
4023 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4024 pc->print(stderr,pc);
4027 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4030 pcfl=setNextItem(PCFL(pcflow)->to);
4033 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4034 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4036 FixRegisterBankingInFlow(PCFL(pcflow),0);
4037 BanksUsedFlow2(pcflow);
4042 Loop through the flow objects again and find the ones with the
4046 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4048 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4050 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4051 pcflow_max_To = pcflow;
4053 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4054 pcflow_max_From = pcflow;
4058 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4059 PCFL(pcflow_max_To)->pc.seq,
4060 PCFL(pcflow_max_To)->ToConflicts);
4063 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4064 PCFL(pcflow_max_From)->pc.seq,
4065 PCFL(pcflow_max_From)->FromConflicts);
4069 /*-----------------------------------------------------------------*/
4070 /*-----------------------------------------------------------------*/
4071 void DumpFlow(pBlock *pb)
4075 pCodeFlowLink *pcfl;
4078 fprintf(stderr,"Dump flow \n");
4079 pb->pcHead->print(stderr, pb->pcHead);
4081 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4082 pcflow->print(stderr,pcflow);
4084 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4086 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4088 if(!isPCFL(pcflow)) {
4089 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4092 fprintf(stderr,"dumping: ");
4093 pcflow->print(stderr,pcflow);
4094 FlowStats(PCFL(pcflow));
4096 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4098 pc = PCODE(pcfl->pcflow);
4100 fprintf(stderr, " from seq %d:\n",pc->seq);
4102 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4103 pc->print(stderr,pc);
4108 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4110 pc = PCODE(pcfl->pcflow);
4112 fprintf(stderr, " to seq %d:\n",pc->seq);
4114 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4115 pc->print(stderr,pc);
4124 /*-----------------------------------------------------------------*/
4125 /*-----------------------------------------------------------------*/
4126 int OptimizepBlock(pBlock *pb)
4131 if(!pb || !peepOptimizing)
4134 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4136 for(pc = pb->pcHead; pc; pc = pc->next)
4137 matches += pCodePeepMatchRule(pc);
4140 pc = findNextInstruction(pb->pcHead);
4145 if(pCodePeepMatchRule(pc)) {
4150 pc = findNextInstruction(pcprev->next);
4152 pc = findNextInstruction(pb->pcHead);
4154 pc = findNextInstruction(pc->next);
4158 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4163 /*-----------------------------------------------------------------*/
4164 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4165 /*-----------------------------------------------------------------*/
4166 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4170 for(pc = pcs; pc; pc = pc->next) {
4172 if((pc->type == PC_OPCODE) &&
4174 (PCI(pc)->pcop->type == PO_LABEL) &&
4175 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4183 /*-----------------------------------------------------------------*/
4184 /*-----------------------------------------------------------------*/
4185 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4190 (PCI(pc)->pcop->type == PO_LABEL)) {
4192 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4194 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4196 free(pcol->pcop.name);
4198 sprintf(buffer,"_%05d_DS_",pcl->key);
4200 pcol->pcop.name = Safe_strdup(buffer);
4201 pcol->key = pcl->key;
4202 //pc->print(stderr,pc);
4209 /*-----------------------------------------------------------------*/
4210 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4211 /* pCode chain if they're not used. */
4212 /*-----------------------------------------------------------------*/
4213 void pBlockRemoveUnusedLabels(pBlock *pb)
4215 pCode *pc; pCodeLabel *pcl;
4220 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4222 pBranch *pbr = PCI(pc)->label;
4223 if(pbr && pbr->next) {
4224 pCode *pcd = pb->pcHead;
4226 //fprintf(stderr, "multiple labels\n");
4227 //pc->print(stderr,pc);
4232 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4233 //fprintf(stderr,"Used by:\n");
4234 //pcd->print(stderr,pcd);
4236 exchangeLabels(PCL(pbr->pc),pcd);
4245 for(pc = pb->pcHead; pc; pc = pc->next) {
4247 if(isPCL(pc)) // pc->type == PC_LABEL)
4249 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4250 pcl = PCL(PCI(pc)->label->pc);
4253 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4255 /* This pCode is a label, so search the pBlock to see if anyone
4258 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4259 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4260 /* Couldn't find an instruction that refers to this label
4261 * So, unlink the pCode label from it's pCode chain
4262 * and destroy the label */
4263 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4265 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4266 if(pc->type == PC_LABEL) {
4268 pCodeLabelDestruct(pc);
4270 unlinkpCodeFromBranch(pc, PCODE(pcl));
4271 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4282 /*-----------------------------------------------------------------*/
4283 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4284 /* chain and put them into pBranches that are */
4285 /* associated with the appropriate pCode */
4287 /*-----------------------------------------------------------------*/
4288 void pBlockMergeLabels(pBlock *pb)
4291 pCode *pc, *pcnext=NULL;
4296 /* First, Try to remove any unused labels */
4297 //pBlockRemoveUnusedLabels(pb);
4299 /* Now loop through the pBlock and merge the labels with the opcodes */
4301 for(pc = pb->pcHead; pc; pc = pc->next) {
4303 if(pc->type == PC_LABEL) {
4305 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4306 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4307 if((pcnext = findNextInstruction(pc) )) {
4309 pCode *pcn = pc->next;
4311 // Unlink the pCode label from it's pCode chain
4314 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4315 // And link it into the instruction's pBranch labels. (Note, since
4316 // it's possible to have multiple labels associated with one instruction
4317 // we must provide a means to accomodate the additional labels. Thus
4318 // the labels are placed into the singly-linked list "label" as
4319 // opposed to being a single member of the pCodeInstruction.)
4321 //_ALLOC(pbr,sizeof(pBranch));
4322 pbr = Safe_calloc(1,sizeof(pBranch));
4327 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4332 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4334 } else if(pc->type == PC_CSOURCE) {
4336 /* merge the source line symbolic info into the next instruction */
4337 if((pcnext = findNextInstruction(pc) )) {
4339 pCode *pcn = pc->next;
4341 // Unlink the pCode label from it's pCode chain
4343 PCI(pcnext)->cline = PCCS(pc);
4344 //fprintf(stderr, "merging CSRC\n");
4345 //genericPrint(stderr,pcnext);
4352 pBlockRemoveUnusedLabels(pb);
4356 /*-----------------------------------------------------------------*/
4357 /*-----------------------------------------------------------------*/
4358 int OptimizepCode(char dbName)
4360 #define MAX_PASSES 4
4369 DFPRINTF((stderr," Optimizing pCode\n"));
4373 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4374 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4375 matches += OptimizepBlock(pb);
4378 while(matches && ++passes < MAX_PASSES);
4383 /*-----------------------------------------------------------------*/
4384 /* popCopyGPR2Bit - copy a pcode operator */
4385 /*-----------------------------------------------------------------*/
4387 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4391 pcop = newpCodeOpBit(pc->name, bitval, 0);
4393 if( !( (pcop->type == PO_LABEL) ||
4394 (pcop->type == PO_LITERAL) ||
4395 (pcop->type == PO_STR) ))
4396 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4404 /*-----------------------------------------------------------------*/
4405 /*-----------------------------------------------------------------*/
4406 int InstructionRegBank(pCode *pc)
4410 if( (reg = getRegFromInstruction(pc)) == NULL)
4413 return REG_BANK(reg);
4418 /*-----------------------------------------------------------------*/
4419 /*-----------------------------------------------------------------*/
4420 void FixRegisterBanking(pBlock *pb)
4432 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4433 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4436 /* loop through all of the flow blocks with in one pblock */
4438 //fprintf(stderr,"Register banking\n");
4441 /* at this point, pc should point to a PC_FLOW object */
4444 /* for each flow block, determine the register banking
4449 //genericPrint(stderr, pc);
4451 reg = getRegFromInstruction(pc);
4454 fprintf(stderr, " %s ",reg->name);
4455 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4459 if(reg && REG_BANK(reg)!=cur_bank) {
4460 /* Examine the instruction before this one to make sure it is
4461 * not a skip type instruction */
4462 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4463 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4464 int b = cur_bank ^ REG_BANK(reg);
4466 //fprintf(stderr, "Cool! can switch banks\n");
4467 cur_bank = REG_BANK(reg);
4469 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4470 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4471 pCodeInsertAfter(pc->prev, new_pc);
4472 if(PCI(pc)->label) {
4473 PCI(new_pc)->label = PCI(pc)->label;
4474 PCI(pc)->label = NULL;
4477 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4478 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4479 pCodeInsertAfter(pc, new_pc);
4485 //fprintf(stderr, "Bummer can't switch banks\n");
4493 // } while(pc && !(isPCFL(pc)));
4498 if(pcprev && cur_bank) {
4499 /* Brute force - make sure that we point to bank 0 at the
4500 * end of each flow block */
4501 new_pc = newpCode(POC_BCF,
4502 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4503 pCodeInsertAfter(pcprev, new_pc);
4509 void pBlockDestruct(pBlock *pb)
4520 /*-----------------------------------------------------------------*/
4521 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4522 /* name dbName and combine them */
4523 /* into one block */
4524 /*-----------------------------------------------------------------*/
4525 void mergepBlocks(char dbName)
4528 pBlock *pb, *pbmerged = NULL,*pbn;
4530 pb = the_pFile->pbHead;
4532 //fprintf(stderr," merging blocks named %c\n",dbName);
4536 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4537 if( getpBlock_dbName(pb) == dbName) {
4539 //fprintf(stderr," merged block %c\n",dbName);
4544 addpCode2pBlock(pbmerged, pb->pcHead);
4545 /* addpCode2pBlock doesn't handle the tail: */
4546 pbmerged->pcTail = pb->pcTail;
4548 pb->prev->next = pbn;
4550 pbn->prev = pb->prev;
4555 //printpBlock(stderr, pbmerged);
4562 /*-----------------------------------------------------------------*/
4563 /* AnalyzeBanking - Called after the memory addresses have been */
4564 /* assigned to the registers. */
4566 /*-----------------------------------------------------------------*/
4567 void AnalyzeBanking(void)
4576 /* Phase 2 - Flow Analysis - Register Banking
4578 * In this phase, the individual flow blocks are examined
4579 * and register banking is fixed.
4582 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4583 //FixRegisterBanking(pb);
4585 /* Phase 2 - Flow Analysis
4587 * In this phase, the pCode is partition into pCodeFlow
4588 * blocks. The flow blocks mark the points where a continuous
4589 * stream of instructions changes flow (e.g. because of
4590 * a call or goto or whatever).
4593 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4597 /* Phase 2 - Flow Analysis - linking flow blocks
4599 * In this phase, the individual flow blocks are examined
4600 * to determine their order of excution.
4603 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4606 /* Phase 3 - Flow Analysis - Flow Tree
4608 * In this phase, the individual flow blocks are examined
4609 * to determine their order of excution.
4612 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4616 /* Phase x - Flow Analysis - Used Banks
4618 * In this phase, the individual flow blocks are examined
4619 * to determine the Register Banks they use
4622 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4625 /* Phase x - Flow Analysis - Used Banks
4627 * In this phase, the individual flow blocks are examined
4628 * to determine the Register Banks they use
4631 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4635 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4636 pCodeRegMapLiveRanges(pb);
4638 RemoveUnusedRegisters();
4640 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4641 pCodeRegOptimizeRegUsage();
4646 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4650 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4652 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4653 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4654 pcflow = pcflow->next) {
4656 FillFlow(PCFL(pcflow));
4660 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4662 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4663 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4664 pcflow = pcflow->next) {
4666 FlowStats(PCFL(pcflow));
4672 /*-----------------------------------------------------------------*/
4673 /* buildCallTree - look at the flow and extract all of the calls */
4675 /*-----------------------------------------------------------------*/
4676 set *register_usage(pBlock *pb);
4678 void buildCallTree(void )
4689 /* Now build the call tree.
4690 First we examine all of the pCodes for functions.
4691 Keep in mind that the function boundaries coincide
4692 with pBlock boundaries.
4694 The algorithm goes something like this:
4695 We have two nested loops. The outer loop iterates
4696 through all of the pBlocks/functions. The inner
4697 loop iterates through all of the pCodes for
4698 a given pBlock. When we begin iterating through
4699 a pBlock, the variable pc_fstart, pCode of the start
4700 of a function, is cleared. We then search for pCodes
4701 of type PC_FUNCTION. When one is encountered, we
4702 initialize pc_fstart to this and at the same time
4703 associate a new pBranch object that signifies a
4704 branch entry. If a return is found, then this signifies
4705 a function exit point. We'll link the pCodes of these
4706 returns to the matching pc_fstart.
4708 When we're done, a doubly linked list of pBranches
4709 will exist. The head of this list is stored in
4710 `the_pFile', which is the meta structure for all
4711 of the pCode. Look at the printCallTree function
4712 on how the pBranches are linked together.
4715 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4716 pCode *pc_fstart=NULL;
4717 for(pc = pb->pcHead; pc; pc = pc->next) {
4719 if (PCF(pc)->fname) {
4721 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4722 //fprintf(stderr," found main \n");
4723 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4727 pbr = Safe_calloc(1,sizeof(pBranch));
4728 pbr->pc = pc_fstart = pc;
4731 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4733 // Here's a better way of doing the same:
4734 addSet(&pb->function_entries, pc);
4737 // Found an exit point in a function, e.g. return
4738 // (Note, there may be more than one return per function)
4740 pBranchLink(PCF(pc_fstart), PCF(pc));
4742 addSet(&pb->function_exits, pc);
4744 } else if(isCALL(pc)) {
4745 addSet(&pb->function_calls,pc);
4750 /* Re-allocate the registers so that there are no collisions
4751 * between local variables when one function call another */
4754 // pic14_deallocateAllRegs();
4756 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4763 /*-----------------------------------------------------------------*/
4764 /* AnalyzepCode - parse the pCode that has been generated and form */
4765 /* all of the logical connections. */
4767 /* Essentially what's done here is that the pCode flow is */
4769 /*-----------------------------------------------------------------*/
4771 void AnalyzepCode(char dbName)
4782 /* Phase 1 - Register allocation and peep hole optimization
4784 * The first part of the analysis is to determine the registers
4785 * that are used in the pCode. Once that is done, the peep rules
4786 * are applied to the code. We continue to loop until no more
4787 * peep rule optimizations are found (or until we exceed the
4788 * MAX_PASSES threshold).
4790 * When done, the required registers will be determined.
4796 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4797 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4799 /* First, merge the labels with the instructions */
4800 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4801 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4803 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4804 //fprintf(stderr," analyze and merging block %c\n",dbName);
4805 pBlockMergeLabels(pb);
4808 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4812 changes = OptimizepCode(dbName);
4814 } while(changes && (i++ < MAX_PASSES));
4819 /*-----------------------------------------------------------------*/
4820 /* ispCodeFunction - returns true if *pc is the pCode of a */
4822 /*-----------------------------------------------------------------*/
4823 bool ispCodeFunction(pCode *pc)
4826 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4832 /*-----------------------------------------------------------------*/
4833 /* findFunction - Search for a function by name (given the name) */
4834 /* in the set of all functions that are in a pBlock */
4835 /* (note - I expect this to change because I'm planning to limit */
4836 /* pBlock's to just one function declaration */
4837 /*-----------------------------------------------------------------*/
4838 pCode *findFunction(char *fname)
4845 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4847 pc = setFirstItem(pb->function_entries);
4850 if((pc->type == PC_FUNCTION) &&
4852 (strcmp(fname, PCF(pc)->fname)==0))
4855 pc = setNextItem(pb->function_entries);
4863 void MarkUsedRegisters(set *regset)
4868 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4869 r2 = pic14_regWithIdx(r1->rIdx);
4875 void pBlockStats(FILE *of, pBlock *pb)
4881 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4883 // for now just print the first element of each set
4884 pc = setFirstItem(pb->function_entries);
4886 fprintf(of,";entry: ");
4889 pc = setFirstItem(pb->function_exits);
4891 fprintf(of,";has an exit\n");
4895 pc = setFirstItem(pb->function_calls);
4897 fprintf(of,";functions called:\n");
4900 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4901 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4903 pc = setNextItem(pb->function_calls);
4907 r = setFirstItem(pb->tregisters);
4909 int n = elementsInSet(pb->tregisters);
4911 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4914 fprintf(of,"; %s\n",r->name);
4915 r = setNextItem(pb->tregisters);
4920 /*-----------------------------------------------------------------*/
4921 /*-----------------------------------------------------------------*/
4923 static void sequencepCode(void)
4929 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4931 pb->seq = GpCodeSequenceNumber+1;
4933 for( pc = pb->pcHead; pc; pc = pc->next)
4934 pc->seq = ++GpCodeSequenceNumber;
4940 /*-----------------------------------------------------------------*/
4941 /*-----------------------------------------------------------------*/
4942 set *register_usage(pBlock *pb)
4945 set *registers=NULL;
4946 set *registersInCallPath = NULL;
4948 /* check recursion */
4950 pc = setFirstItem(pb->function_entries);
4957 if(pc->type != PC_FUNCTION)
4958 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4960 pc = setFirstItem(pb->function_calls);
4961 for( ; pc; pc = setNextItem(pb->function_calls)) {
4963 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4964 char *dest = get_op_from_instruction(PCI(pc));
4966 pcn = findFunction(dest);
4968 registersInCallPath = register_usage(pcn->pb);
4970 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4975 pBlockStats(stderr,pb); // debug
4978 // Mark the registers in this block as used.
4980 MarkUsedRegisters(pb->tregisters);
4981 if(registersInCallPath) {
4982 /* registers were used in the functions this pBlock has called */
4983 /* so now, we need to see if these collide with the ones we are */
4986 regs *r1,*r2, *newreg;
4988 DFPRINTF((stderr,"comparing registers\n"));
4990 r1 = setFirstItem(registersInCallPath);
4993 r2 = setFirstItem(pb->tregisters);
4995 while(r2 && (r1->type != REG_STK)) {
4997 if(r2->rIdx == r1->rIdx) {
4998 newreg = pic14_findFreeReg(REG_GPR);
5002 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5006 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5007 r1->rIdx, newreg->rIdx));
5008 r2->rIdx = newreg->rIdx;
5009 //if(r2->name) free(r2->name);
5011 r2->name = Safe_strdup(newreg->name);
5015 newreg->wasUsed = 1;
5017 r2 = setNextItem(pb->tregisters);
5020 r1 = setNextItem(registersInCallPath);
5023 /* Collisions have been resolved. Now free the registers in the call path */
5024 r1 = setFirstItem(registersInCallPath);
5026 if(r1->type != REG_STK) {
5027 newreg = pic14_regWithIdx(r1->rIdx);
5030 r1 = setNextItem(registersInCallPath);
5034 // MarkUsedRegisters(pb->registers);
5036 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5039 DFPRINTF((stderr,"returning regs\n"));
5041 DFPRINTF((stderr,"not returning regs\n"));
5043 DFPRINTF((stderr,"pBlock after register optim.\n"));
5044 pBlockStats(stderr,pb); // debug
5050 /*-----------------------------------------------------------------*/
5051 /* printCallTree - writes the call tree to a file */
5053 /*-----------------------------------------------------------------*/
5054 void pct2(FILE *of,pBlock *pb,int indent)
5058 // set *registersInCallPath = NULL;
5064 return; //recursion ?
5066 pc = setFirstItem(pb->function_entries);
5073 for(i=0;i<indent;i++) // Indentation
5076 if(pc->type == PC_FUNCTION)
5077 fprintf(of,"%s\n",PCF(pc)->fname);
5082 pc = setFirstItem(pb->function_calls);
5083 for( ; pc; pc = setNextItem(pb->function_calls)) {
5085 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5086 char *dest = get_op_from_instruction(PCI(pc));
5088 pcn = findFunction(dest);
5090 pct2(of,pcn->pb,indent+1);
5092 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5100 /*-----------------------------------------------------------------*/
5101 /* printCallTree - writes the call tree to a file */
5103 /*-----------------------------------------------------------------*/
5105 void printCallTree(FILE *of)
5117 fprintf(of, "\npBlock statistics\n");
5118 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5123 fprintf(of,"Call Tree\n");
5124 pbr = the_pFile->functions;
5128 if(!ispCodeFunction(pc))
5129 fprintf(of,"bug in call tree");
5132 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5134 while(pc->next && !ispCodeFunction(pc->next)) {
5136 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5137 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5145 fprintf(of,"\n**************\n\na better call tree\n");
5146 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5151 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5152 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5158 /*-----------------------------------------------------------------*/
5160 /*-----------------------------------------------------------------*/
5162 void InlineFunction(pBlock *pb)
5170 pc = setFirstItem(pb->function_calls);
5172 for( ; pc; pc = setNextItem(pb->function_calls)) {
5175 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5181 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5183 //fprintf(stderr,"Cool can inline:\n");
5184 //pcn->print(stderr,pcn);
5186 //fprintf(stderr,"recursive call Inline\n");
5187 InlineFunction(pcn->pb);
5188 //fprintf(stderr,"return from recursive call Inline\n");
5191 At this point, *pc points to a CALL mnemonic, and
5192 *pcn points to the function that is being called.
5194 To in-line this call, we need to remove the CALL
5195 and RETURN(s), and link the function pCode in with
5201 /* Remove the CALL */
5205 /* remove callee pBlock from the pBlock linked list */
5206 removepBlock(pcn->pb);
5214 /* Remove the Function pCode */
5215 pct = findNextInstruction(pcn->next);
5217 /* Link the function with the callee */
5218 pc->next = pcn->next;
5219 pcn->next->prev = pc;
5221 /* Convert the function name into a label */
5223 pbr = Safe_calloc(1,sizeof(pBranch));
5224 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5226 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5227 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5229 /* turn all of the return's except the last into goto's */
5230 /* check case for 2 instruction pBlocks */
5231 pce = findNextInstruction(pcn->next);
5233 pCode *pce_next = findNextInstruction(pce->next);
5235 if(pce_next == NULL) {
5236 /* found the last return */
5237 pCode *pc_call_next = findNextInstruction(pc_call->next);
5239 //fprintf(stderr,"found last return\n");
5240 //pce->print(stderr,pce);
5241 pce->prev->next = pc_call->next;
5242 pc_call->next->prev = pce->prev;
5243 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5253 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5259 /*-----------------------------------------------------------------*/
5261 /*-----------------------------------------------------------------*/
5263 void InlinepCode(void)
5272 if(!functionInlining)
5275 /* Loop through all of the function definitions and count the
5276 * number of times each one is called */
5277 //fprintf(stderr,"inlining %d\n",__LINE__);
5279 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5281 pc = setFirstItem(pb->function_calls);
5283 for( ; pc; pc = setNextItem(pb->function_calls)) {
5286 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5287 if(pcn && isPCF(pcn)) {
5288 PCF(pcn)->ncalled++;
5291 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5296 //fprintf(stderr,"inlining %d\n",__LINE__);
5298 /* Now, Loop through the function definitions again, but this
5299 * time inline those functions that have only been called once. */
5301 InlineFunction(the_pFile->pbHead);
5302 //fprintf(stderr,"inlining %d\n",__LINE__);
5304 for(pb = the_pFile->pbHead; pb; pb = pb->next)