1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
78 int debug_verbose = 0; /* Set true to inundate .asm file */
80 static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
88 /****************************************************************/
89 /* Forward declarations */
90 /****************************************************************/
92 void unlinkpCode(pCode *pc);
94 static void genericAnalyze(pCode *pc);
95 static void AnalyzeGOTO(pCode *pc);
96 static void AnalyzeSKIP(pCode *pc);
97 static void AnalyzeRETURN(pCode *pc);
100 static void genericDestruct(pCode *pc);
101 static void genericPrint(FILE *of,pCode *pc);
103 static void pCodePrintLabel(FILE *of, pCode *pc);
104 static void pCodePrintFunction(FILE *of, pCode *pc);
105 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
106 static char *get_op_from_instruction( pCodeInstruction *pcc);
107 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
108 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
109 int pCodePeepMatchRule(pCode *pc);
110 void pBlockStats(FILE *of, pBlock *pb);
111 pBlock *newpBlock(void);
112 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
113 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
114 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
115 void pCodeRegMapLiveRanges(pBlock *pb);
118 /****************************************************************/
119 /* PIC Instructions */
120 /****************************************************************/
122 pCodeInstruction pciADDWF = {
123 {PC_OPCODE, NULL, NULL, 0, NULL,
136 1,0, // dest, bit instruction
139 (PCC_W | PCC_REGISTER), // inCond
140 (PCC_REGISTER | PCC_Z) // outCond
143 pCodeInstruction pciADDFW = {
144 {PC_OPCODE, NULL, NULL, 0, NULL,
157 0,0, // dest, bit instruction
160 (PCC_W | PCC_REGISTER), // inCond
161 (PCC_W | PCC_Z) // outCond
164 pCodeInstruction pciADDLW = {
165 {PC_OPCODE, NULL, NULL, 0, NULL,
178 0,0, // dest, bit instruction
181 (PCC_W | PCC_LITERAL), // inCond
182 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
185 pCodeInstruction pciANDLW = {
186 {PC_OPCODE, NULL, NULL, 0, NULL,
199 0,0, // dest, bit instruction
202 (PCC_W | PCC_LITERAL), // inCond
203 (PCC_W | PCC_Z) // outCond
206 pCodeInstruction pciANDWF = {
207 {PC_OPCODE, NULL, NULL, 0, NULL,
220 1,0, // dest, bit instruction
223 (PCC_W | PCC_REGISTER), // inCond
224 (PCC_REGISTER | PCC_Z) // outCond
227 pCodeInstruction pciANDFW = {
228 {PC_OPCODE, NULL, NULL, 0, NULL,
241 0,0, // dest, bit instruction
244 (PCC_W | PCC_REGISTER), // inCond
245 (PCC_W | PCC_Z) // outCond
248 pCodeInstruction pciBCF = {
249 {PC_OPCODE, NULL, NULL, 0, NULL,
262 1,1, // dest, bit instruction
265 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
266 PCC_REGISTER // outCond
269 pCodeInstruction pciBSF = {
270 {PC_OPCODE, NULL, NULL, 0, NULL,
283 1,1, // dest, bit instruction
286 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
287 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
290 pCodeInstruction pciBTFSC = {
291 {PC_OPCODE, NULL, NULL, 0, NULL,
304 0,1, // dest, bit instruction
307 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
308 PCC_EXAMINE_PCOP // outCond
311 pCodeInstruction pciBTFSS = {
312 {PC_OPCODE, NULL, NULL, 0, NULL,
325 0,1, // dest, bit instruction
328 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
329 PCC_EXAMINE_PCOP // outCond
332 pCodeInstruction pciCALL = {
333 {PC_OPCODE, NULL, NULL, 0, NULL,
346 0,0, // dest, bit instruction
353 pCodeInstruction pciCOMF = {
354 {PC_OPCODE, NULL, NULL, 0, NULL,
367 1,0, // dest, bit instruction
370 PCC_REGISTER, // inCond
371 PCC_REGISTER // outCond
374 pCodeInstruction pciCOMFW = {
375 {PC_OPCODE, NULL, NULL, 0, NULL,
388 0,0, // dest, bit instruction
391 PCC_REGISTER, // inCond
395 pCodeInstruction pciCLRF = {
396 {PC_OPCODE, NULL, NULL, 0, NULL,
409 0,0, // dest, bit instruction
413 PCC_REGISTER // outCond
416 pCodeInstruction pciCLRW = {
417 {PC_OPCODE, NULL, NULL, 0, NULL,
430 0,0, // dest, bit instruction
437 pCodeInstruction pciDECF = {
438 {PC_OPCODE, NULL, NULL, 0, NULL,
451 1,0, // dest, bit instruction
454 PCC_REGISTER, // inCond
455 PCC_REGISTER // outCond
458 pCodeInstruction pciDECFW = {
459 {PC_OPCODE, NULL, NULL, 0, NULL,
472 0,0, // dest, bit instruction
475 PCC_REGISTER, // inCond
479 pCodeInstruction pciDECFSZ = {
480 {PC_OPCODE, NULL, NULL, 0, NULL,
493 1,0, // dest, bit instruction
496 PCC_REGISTER, // inCond
497 PCC_REGISTER // outCond
500 pCodeInstruction pciDECFSZW = {
501 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
517 PCC_REGISTER, // inCond
521 pCodeInstruction pciGOTO = {
522 {PC_OPCODE, NULL, NULL, 0, NULL,
535 0,0, // dest, bit instruction
542 pCodeInstruction pciINCF = {
543 {PC_OPCODE, NULL, NULL, 0, NULL,
556 1,0, // dest, bit instruction
559 PCC_REGISTER, // inCond
560 PCC_REGISTER // outCond
563 pCodeInstruction pciINCFW = {
564 {PC_OPCODE, NULL, NULL, 0, NULL,
577 0,0, // dest, bit instruction
580 PCC_REGISTER, // inCond
584 pCodeInstruction pciINCFSZ = {
585 {PC_OPCODE, NULL, NULL, 0, NULL,
598 1,0, // dest, bit instruction
601 PCC_REGISTER, // inCond
602 PCC_REGISTER // outCond
605 pCodeInstruction pciINCFSZW = {
606 {PC_OPCODE, NULL, NULL, 0, NULL,
619 0,0, // dest, bit instruction
622 PCC_REGISTER, // inCond
626 pCodeInstruction pciIORWF = {
627 {PC_OPCODE, NULL, NULL, 0, NULL,
640 1,0, // dest, bit instruction
643 (PCC_W | PCC_REGISTER), // inCond
644 (PCC_REGISTER | PCC_Z) // outCond
647 pCodeInstruction pciIORFW = {
648 {PC_OPCODE, NULL, NULL, 0, NULL,
661 0,0, // dest, bit instruction
664 (PCC_W | PCC_REGISTER), // inCond
665 (PCC_W | PCC_Z) // outCond
668 pCodeInstruction pciIORLW = {
669 {PC_OPCODE, NULL, NULL, 0, NULL,
682 0,0, // dest, bit instruction
685 (PCC_W | PCC_LITERAL), // inCond
686 (PCC_W | PCC_Z) // outCond
689 pCodeInstruction pciMOVF = {
690 {PC_OPCODE, NULL, NULL, 0, NULL,
703 1,0, // dest, bit instruction
706 PCC_REGISTER, // inCond
710 pCodeInstruction pciMOVFW = {
711 {PC_OPCODE, NULL, NULL, 0, NULL,
724 0,0, // dest, bit instruction
727 PCC_REGISTER, // inCond
728 (PCC_W | PCC_Z) // outCond
731 pCodeInstruction pciMOVWF = {
732 {PC_OPCODE, NULL, NULL, 0, NULL,
745 0,0, // dest, bit instruction
749 PCC_REGISTER // outCond
752 pCodeInstruction pciMOVLW = {
753 {PC_OPCODE, NULL, NULL, 0, NULL,
766 0,0, // dest, bit instruction
769 (PCC_NONE | PCC_LITERAL), // inCond
773 pCodeInstruction pciNOP = {
774 {PC_OPCODE, NULL, NULL, 0, NULL,
786 0,0, // dest, bit instruction
793 pCodeInstruction pciRETFIE = {
794 {PC_OPCODE, NULL, NULL, 0, NULL,
807 0,0, // dest, bit instruction
811 PCC_NONE // outCond (not true... affects the GIE bit too)
814 pCodeInstruction pciRETLW = {
815 {PC_OPCODE, NULL, NULL, 0, NULL,
828 0,0, // dest, bit instruction
831 PCC_LITERAL, // inCond
835 pCodeInstruction pciRETURN = {
836 {PC_OPCODE, NULL, NULL, 0, NULL,
849 0,0, // dest, bit instruction
856 pCodeInstruction pciRLF = {
857 {PC_OPCODE, NULL, NULL, 0, NULL,
870 1,0, // dest, bit instruction
873 (PCC_C | PCC_REGISTER), // inCond
874 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
877 pCodeInstruction pciRLFW = {
878 {PC_OPCODE, NULL, NULL, 0, NULL,
891 0,0, // dest, bit instruction
894 (PCC_C | PCC_REGISTER), // inCond
895 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
898 pCodeInstruction pciRRF = {
899 {PC_OPCODE, NULL, NULL, 0, NULL,
912 1,0, // dest, bit instruction
915 (PCC_C | PCC_REGISTER), // inCond
916 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
919 pCodeInstruction pciRRFW = {
920 {PC_OPCODE, NULL, NULL, 0, NULL,
933 0,0, // dest, bit instruction
936 (PCC_C | PCC_REGISTER), // inCond
937 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
940 pCodeInstruction pciSUBWF = {
941 {PC_OPCODE, NULL, NULL, 0, NULL,
954 1,0, // dest, bit instruction
957 (PCC_W | PCC_REGISTER), // inCond
958 (PCC_REGISTER | PCC_Z) // outCond
961 pCodeInstruction pciSUBFW = {
962 {PC_OPCODE, NULL, NULL, 0, NULL,
975 0,0, // dest, bit instruction
978 (PCC_W | PCC_REGISTER), // inCond
979 (PCC_W | PCC_Z) // outCond
982 pCodeInstruction pciSUBLW = {
983 {PC_OPCODE, NULL, NULL, 0, NULL,
996 0,0, // dest, bit instruction
999 (PCC_W | PCC_LITERAL), // inCond
1000 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1003 pCodeInstruction pciSWAPF = {
1004 {PC_OPCODE, NULL, NULL, 0, NULL,
1010 NULL, // from branch
1017 1,0, // dest, bit instruction
1018 0,0, // branch, skip
1020 (PCC_REGISTER), // inCond
1021 (PCC_REGISTER) // outCond
1024 pCodeInstruction pciSWAPFW = {
1025 {PC_OPCODE, NULL, NULL, 0, NULL,
1031 NULL, // from branch
1038 0,0, // dest, bit instruction
1039 0,0, // branch, skip
1041 (PCC_REGISTER), // inCond
1045 pCodeInstruction pciTRIS = {
1046 {PC_OPCODE, NULL, NULL, 0, NULL,
1052 NULL, // from branch
1059 0,0, // dest, bit instruction
1060 0,0, // branch, skip
1063 PCC_REGISTER // outCond
1066 pCodeInstruction pciXORWF = {
1067 {PC_OPCODE, NULL, NULL, 0, NULL,
1073 NULL, // from branch
1080 1,0, // dest, bit instruction
1081 0,0, // branch, skip
1083 (PCC_W | PCC_REGISTER), // inCond
1084 (PCC_REGISTER | PCC_Z) // outCond
1087 pCodeInstruction pciXORFW = {
1088 {PC_OPCODE, NULL, NULL, 0, NULL,
1094 NULL, // from branch
1101 0,0, // dest, bit instruction
1102 0,0, // branch, skip
1104 (PCC_W | PCC_REGISTER), // inCond
1105 (PCC_W | PCC_Z) // outCond
1108 pCodeInstruction pciXORLW = {
1109 {PC_OPCODE, NULL, NULL, 0, NULL,
1115 NULL, // from branch
1122 0,0, // dest, bit instruction
1123 0,0, // branch, skip
1125 (PCC_W | PCC_LITERAL), // inCond
1126 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1130 #define MAX_PIC14MNEMONICS 100
1131 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1133 /* This definition needs to be part of configure.in */
1134 // #define USE_VSNPRINTF
1136 #ifdef USE_VSNPRINTF
1137 // Alas, vsnprintf is not ANSI standard, and does not exist
1138 // on Solaris (and probably other non-Gnu flavored Unixes).
1140 /*-----------------------------------------------------------------*/
1141 /* SAFE_snprintf - like snprintf except the string pointer is */
1142 /* after the string has been printed to. This is */
1143 /* useful for printing to string as though if it */
1144 /* were a stream. */
1145 /*-----------------------------------------------------------------*/
1146 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1154 va_start(val, format);
1156 vsnprintf(*str, *size, format, val);
1162 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1163 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1171 #else // USE_VSNPRINTF
1173 // This version is *not* safe, despite the name.
1175 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1179 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1184 va_start(val, format);
1186 vsprintf(buffer, format, val);
1189 len = strlen(buffer);
1191 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1192 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1195 strcpy(*str, buffer);
1201 #endif // USE_VSNPRINTF
1204 extern void initStack(int base_address, int size);
1205 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1206 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1207 extern void init_pic(char *);
1209 void pCodeInitRegisters(void)
1211 static int initialized=0;
1217 initStack(0xfff, 8);
1218 init_pic(port->processor);
1220 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1221 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1222 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1223 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1224 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1225 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1227 pc_status.rIdx = IDX_STATUS;
1228 pc_fsr.rIdx = IDX_FSR;
1229 pc_indf.rIdx = IDX_INDF;
1230 pc_intcon.rIdx = IDX_INTCON;
1231 pc_pcl.rIdx = IDX_PCL;
1232 pc_pclath.rIdx = IDX_PCLATH;
1234 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1235 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1236 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1238 pc_kzero.rIdx = IDX_KZ;
1239 pc_wsave.rIdx = IDX_WSAVE;
1240 pc_ssave.rIdx = IDX_SSAVE;
1242 /* probably should put this in a separate initialization routine */
1243 pb_dead_pcodes = newpBlock();
1247 /*-----------------------------------------------------------------*/
1248 /* mnem2key - convert a pic mnemonic into a hash key */
1249 /* (BTW - this spreads the mnemonics quite well) */
1251 /*-----------------------------------------------------------------*/
1253 int mnem2key(char const *mnem)
1262 key += toupper(*mnem++) +1;
1266 return (key & 0x1f);
1270 void pic14initMnemonics(void)
1275 pCodeInstruction *pci;
1277 if(mnemonics_initialized)
1280 //FIXME - probably should NULL out the array before making the assignments
1281 //since we check the array contents below this initialization.
1283 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1284 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1285 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1286 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1287 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1288 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1289 pic14Mnemonics[POC_BCF] = &pciBCF;
1290 pic14Mnemonics[POC_BSF] = &pciBSF;
1291 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1292 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1293 pic14Mnemonics[POC_CALL] = &pciCALL;
1294 pic14Mnemonics[POC_COMF] = &pciCOMF;
1295 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1296 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1297 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1298 pic14Mnemonics[POC_DECF] = &pciDECF;
1299 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1300 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1301 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1302 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1303 pic14Mnemonics[POC_INCF] = &pciINCF;
1304 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1305 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1306 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1307 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1308 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1309 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1310 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1311 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1312 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1313 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1314 pic14Mnemonics[POC_NOP] = &pciNOP;
1315 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1316 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1317 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1318 pic14Mnemonics[POC_RLF] = &pciRLF;
1319 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1320 pic14Mnemonics[POC_RRF] = &pciRRF;
1321 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1322 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1323 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1324 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1325 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1326 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1327 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1328 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1329 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1330 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1332 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1333 if(pic14Mnemonics[i])
1334 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1335 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1338 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1339 pci = hTabNextItem(pic14MnemonicsHash, &key);
1342 mnemonics_initialized = 1;
1345 int getpCodePeepCommand(char *cmd);
1347 int getpCode(char *mnem,unsigned dest)
1350 pCodeInstruction *pci;
1351 int key = mnem2key(mnem);
1353 if(!mnemonics_initialized)
1354 pic14initMnemonics();
1356 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1360 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1361 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1365 pci = hTabNextItemWK (pic14MnemonicsHash);
1372 /*-----------------------------------------------------------------*
1373 * pic14initpCodePeepCommands
1375 *-----------------------------------------------------------------*/
1376 void pic14initpCodePeepCommands(void)
1384 hTabAddItem(&pic14pCodePeepCommandsHash,
1385 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1387 } while (peepCommands[i].cmd);
1389 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1392 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1393 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1398 /*-----------------------------------------------------------------
1401 *-----------------------------------------------------------------*/
1403 int getpCodePeepCommand(char *cmd)
1407 int key = mnem2key(cmd);
1410 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1413 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1414 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1418 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1425 char getpBlock_dbName(pBlock *pb)
1431 return pb->cmemmap->dbName;
1435 void pBlockConvert2ISR(pBlock *pb)
1446 /*-----------------------------------------------------------------*/
1447 /* movepBlock2Head - given the dbname of a pBlock, move all */
1448 /* instances to the front of the doubly linked */
1449 /* list of pBlocks */
1450 /*-----------------------------------------------------------------*/
1452 void movepBlock2Head(char dbName)
1456 pb = the_pFile->pbHead;
1460 if(getpBlock_dbName(pb) == dbName) {
1461 pBlock *pbn = pb->next;
1462 pb->next = the_pFile->pbHead;
1463 the_pFile->pbHead->prev = pb;
1464 the_pFile->pbHead = pb;
1467 pb->prev->next = pbn;
1469 // If the pBlock that we just moved was the last
1470 // one in the link of all of the pBlocks, then we
1471 // need to point the tail to the block just before
1472 // the one we moved.
1473 // Note: if pb->next is NULL, then pb must have
1474 // been the last pBlock in the chain.
1477 pbn->prev = pb->prev;
1479 the_pFile->pbTail = pb->prev;
1490 void copypCode(FILE *of, char dbName)
1494 if(!of || !the_pFile)
1497 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1498 if(getpBlock_dbName(pb) == dbName) {
1505 void pcode_test(void)
1508 DFPRINTF((stderr,"pcode is alive!\n"));
1518 /* create the file name */
1519 strcpy(buffer,srcFileName);
1520 strcat(buffer,".p");
1522 if( !(pFile = fopen(buffer, "w" ))) {
1523 werror(E_FILE_OPEN_ERR,buffer);
1527 fprintf(pFile,"pcode dump\n\n");
1529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1530 fprintf(pFile,"\n\tNew pBlock\n\n");
1532 fprintf(pFile,"%s",pb->cmemmap->sname);
1534 fprintf(pFile,"internal pblock");
1536 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1537 printpBlock(pFile,pb);
1541 /*-----------------------------------------------------------------*/
1542 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1543 /* ister, RegCond will return the bit being referenced. */
1545 /* fixme - why not just OR in the pcop bit field */
1546 /*-----------------------------------------------------------------*/
1548 static int RegCond(pCodeOp *pcop)
1554 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1555 switch(PCORB(pcop)->bit) {
1569 /*-----------------------------------------------------------------*/
1570 /* newpCode - create and return a newly initialized pCode */
1572 /* fixme - rename this */
1574 /* The purpose of this routine is to create a new Instruction */
1575 /* pCode. This is called by gen.c while the assembly code is being */
1579 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1580 /* (note that the op is analogous to but not the */
1581 /* same thing as the opcode of the instruction.) */
1582 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1585 /* a pointer to the new malloc'd pCode is returned. */
1589 /*-----------------------------------------------------------------*/
1590 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1592 pCodeInstruction *pci ;
1594 if(!mnemonics_initialized)
1595 pic14initMnemonics();
1597 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1599 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1600 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1603 if(pci->inCond & PCC_EXAMINE_PCOP)
1604 pci->inCond |= RegCond(pcop);
1606 if(pci->outCond & PCC_EXAMINE_PCOP)
1607 pci->outCond |= RegCond(pcop);
1609 pci->pc.prev = pci->pc.next = NULL;
1610 return (pCode *)pci;
1613 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1619 /*-----------------------------------------------------------------*/
1620 /* newpCodeWild - create a "wild" as in wild card pCode */
1622 /* Wild pcodes are used during the peep hole optimizer to serve */
1623 /* as place holders for any instruction. When a snippet of code is */
1624 /* compared to a peep hole rule, the wild card opcode will match */
1625 /* any instruction. However, the optional operand and label are */
1626 /* additional qualifiers that must also be matched before the */
1627 /* line (of assembly code) is declared matched. Note that the */
1628 /* operand may be wild too. */
1630 /* Note, a wild instruction is specified just like a wild var: */
1631 /* %4 ; A wild instruction, */
1632 /* See the peeph.def file for additional examples */
1634 /*-----------------------------------------------------------------*/
1636 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1641 pcw = Safe_calloc(1,sizeof(pCodeWild));
1643 pcw->pci.pc.type = PC_WILD;
1644 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1645 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1646 pcw->pci.pc.pb = NULL;
1648 // pcw->pci.pc.analyze = genericAnalyze;
1649 pcw->pci.pc.destruct = genericDestruct;
1650 pcw->pci.pc.print = genericPrint;
1652 pcw->id = pCodeID; // this is the 'n' in %n
1653 pcw->operand = optional_operand;
1654 pcw->label = optional_label;
1656 pcw->mustBeBitSkipInst = 0;
1657 pcw->mustNotBeBitSkipInst = 0;
1658 pcw->invertBitSkipInst = 0;
1660 return ( (pCode *)pcw);
1664 /*-----------------------------------------------------------------*/
1665 /* newPcodeInlineP - create a new pCode from a char string */
1666 /*-----------------------------------------------------------------*/
1669 pCode *newpCodeInlineP(char *cP)
1674 pcc = Safe_calloc(1,sizeof(pCodeComment));
1676 pcc->pc.type = PC_INLINE;
1677 pcc->pc.prev = pcc->pc.next = NULL;
1678 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1681 // pcc->pc.analyze = genericAnalyze;
1682 pcc->pc.destruct = genericDestruct;
1683 pcc->pc.print = genericPrint;
1686 pcc->comment = Safe_strdup(cP);
1688 pcc->comment = NULL;
1690 return ( (pCode *)pcc);
1694 /*-----------------------------------------------------------------*/
1695 /* newPcodeCharP - create a new pCode from a char string */
1696 /*-----------------------------------------------------------------*/
1698 pCode *newpCodeCharP(char *cP)
1703 pcc = Safe_calloc(1,sizeof(pCodeComment));
1705 pcc->pc.type = PC_COMMENT;
1706 pcc->pc.prev = pcc->pc.next = NULL;
1707 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1710 // pcc->pc.analyze = genericAnalyze;
1711 pcc->pc.destruct = genericDestruct;
1712 pcc->pc.print = genericPrint;
1715 pcc->comment = Safe_strdup(cP);
1717 pcc->comment = NULL;
1719 return ( (pCode *)pcc);
1723 /*-----------------------------------------------------------------*/
1724 /* newpCodeFunction - */
1725 /*-----------------------------------------------------------------*/
1728 pCode *newpCodeFunction(char *mod,char *f)
1732 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1733 //_ALLOC(pcf,sizeof(pCodeFunction));
1735 pcf->pc.type = PC_FUNCTION;
1736 pcf->pc.prev = pcf->pc.next = NULL;
1737 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1740 // pcf->pc.analyze = genericAnalyze;
1741 pcf->pc.destruct = genericDestruct;
1742 pcf->pc.print = pCodePrintFunction;
1747 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1748 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1749 strcpy(pcf->modname,mod);
1751 pcf->modname = NULL;
1754 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1755 pcf->fname = Safe_calloc(1,strlen(f)+1);
1756 strcpy(pcf->fname,f);
1760 return ( (pCode *)pcf);
1764 /*-----------------------------------------------------------------*/
1766 /*-----------------------------------------------------------------*/
1767 void destructpCodeFlow(pCode *pc)
1769 if(!pc || !isPCFL(pc))
1778 deleteSet(&PCFL(pc)->registers);
1779 deleteSet(&PCFL(pc)->from);
1780 deleteSet(&PCFL(pc)->to);
1785 pCode *newpCodeFlow(void )
1789 //_ALLOC(pcflow,sizeof(pCodeFlow));
1790 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1792 pcflow->pc.type = PC_FLOW;
1793 pcflow->pc.prev = pcflow->pc.next = NULL;
1794 pcflow->pc.pb = NULL;
1796 // pcflow->pc.analyze = genericAnalyze;
1797 pcflow->pc.destruct = destructpCodeFlow;
1798 pcflow->pc.print = genericPrint;
1800 pcflow->pc.seq = GpcFlowSeq++;
1802 pcflow->from = pcflow->to = NULL;
1804 pcflow->inCond = PCC_NONE;
1805 pcflow->outCond = PCC_NONE;
1807 pcflow->firstBank = -1;
1808 pcflow->lastBank = -1;
1810 pcflow->FromConflicts = 0;
1811 pcflow->ToConflicts = 0;
1815 pcflow->registers = newSet();
1817 return ( (pCode *)pcflow);
1821 /*-----------------------------------------------------------------*/
1822 /*-----------------------------------------------------------------*/
1823 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1825 pCodeFlowLink *pcflowLink;
1827 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1829 pcflowLink->pcflow = pcflow;
1830 pcflowLink->bank_conflict = 0;
1835 /*-----------------------------------------------------------------*/
1836 /* newpCodeCSource - create a new pCode Source Symbol */
1837 /*-----------------------------------------------------------------*/
1839 pCode *newpCodeCSource(int ln, char *f, char *l)
1844 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1846 pccs->pc.type = PC_CSOURCE;
1847 pccs->pc.prev = pccs->pc.next = NULL;
1850 pccs->pc.destruct = genericDestruct;
1851 pccs->pc.print = genericPrint;
1853 pccs->line_number = ln;
1855 pccs->line = Safe_strdup(l);
1860 pccs->file_name = Safe_strdup(f);
1862 pccs->file_name = NULL;
1864 return ( (pCode *)pccs);
1867 /*-----------------------------------------------------------------*/
1868 /* pCodeLabelDestruct - free memory used by a label. */
1869 /*-----------------------------------------------------------------*/
1870 static void pCodeLabelDestruct(pCode *pc)
1876 if((pc->type == PC_LABEL) && PCL(pc)->label)
1877 free(PCL(pc)->label);
1883 pCode *newpCodeLabel(char *name, int key)
1889 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1891 pcl->pc.type = PC_LABEL;
1892 pcl->pc.prev = pcl->pc.next = NULL;
1893 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1896 // pcl->pc.analyze = genericAnalyze;
1897 pcl->pc.destruct = pCodeLabelDestruct;
1898 pcl->pc.print = pCodePrintLabel;
1904 sprintf(s,"_%05d_DS_",key);
1909 pcl->label = Safe_strdup(s);
1912 return ( (pCode *)pcl);
1917 /*-----------------------------------------------------------------*/
1918 /* newpBlock - create and return a pointer to a new pBlock */
1919 /*-----------------------------------------------------------------*/
1920 pBlock *newpBlock(void)
1925 PpB = Safe_calloc(1,sizeof(pBlock) );
1926 PpB->next = PpB->prev = NULL;
1928 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1929 PpB->tregisters = NULL;
1931 PpB->FlowTree = NULL;
1937 /*-----------------------------------------------------------------*/
1938 /* newpCodeChain - create a new chain of pCodes */
1939 /*-----------------------------------------------------------------*
1941 * This function will create a new pBlock and the pointer to the
1942 * pCode that is passed in will be the first pCode in the block.
1943 *-----------------------------------------------------------------*/
1946 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1949 pBlock *pB = newpBlock();
1951 pB->pcHead = pB->pcTail = pc;
1958 /*-----------------------------------------------------------------*/
1959 /* newpCodeOpLabel - Create a new label given the key */
1960 /* Note, a negative key means that the label is part of wild card */
1961 /* (and hence a wild card label) used in the pCodePeep */
1962 /* optimizations). */
1963 /*-----------------------------------------------------------------*/
1965 pCodeOp *newpCodeOpLabel(char *name, int key)
1968 static int label_key=-1;
1972 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1973 pcop->type = PO_LABEL;
1978 sprintf(s=buffer,"_%05d_DS_",key);
1980 s = name, key = label_key--;
1983 pcop->name = Safe_strdup(s);
1985 ((pCodeOpLabel *)pcop)->key = key;
1990 /*-----------------------------------------------------------------*/
1991 /*-----------------------------------------------------------------*/
1992 pCodeOp *newpCodeOpLit(int lit)
1998 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1999 pcop->type = PO_LITERAL;
2003 sprintf(s,"0x%02x",lit);
2005 pcop->name = Safe_strdup(s);
2008 ((pCodeOpLit *)pcop)->lit = lit;
2013 /*-----------------------------------------------------------------*/
2014 /*-----------------------------------------------------------------*/
2015 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2019 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2020 pcop->type = PO_IMMEDIATE;
2022 regs *r = dirregWithName(name);
2023 pcop->name = Safe_strdup(name);
2026 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2027 PCOI(pcop)->rIdx = r->rIdx;
2029 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2030 PCOI(pcop)->rIdx = -1;
2032 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2037 PCOI(pcop)->index = index;
2038 PCOI(pcop)->offset = offset;
2039 PCOI(pcop)->_const = code_space;
2044 /*-----------------------------------------------------------------*/
2045 /*-----------------------------------------------------------------*/
2046 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2052 if(!pcwb || !subtype) {
2053 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2057 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2058 pcop->type = PO_WILD;
2059 sprintf(s,"%%%d",id);
2060 pcop->name = Safe_strdup(s);
2062 PCOW(pcop)->id = id;
2063 PCOW(pcop)->pcwb = pcwb;
2064 PCOW(pcop)->subtype = subtype;
2065 PCOW(pcop)->matched = NULL;
2070 /*-----------------------------------------------------------------*/
2071 /*-----------------------------------------------------------------*/
2072 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2076 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2077 pcop->type = PO_GPR_BIT;
2079 pcop->name = Safe_strdup(s);
2083 PCORB(pcop)->bit = bit;
2084 PCORB(pcop)->inBitSpace = inBitSpace;
2089 /*-----------------------------------------------------------------*
2090 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2092 * If rIdx >=0 then a specific register from the set of registers
2093 * will be selected. If rIdx <0, then a new register will be searched
2095 *-----------------------------------------------------------------*/
2097 pCodeOp *newpCodeOpReg(int rIdx)
2101 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106 PCOR(pcop)->rIdx = rIdx;
2107 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2109 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2112 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2116 pcop->type = PCOR(pcop)->r->pc_type;
2121 pCodeOp *newpCodeOpRegFromStr(char *name)
2125 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2126 PCOR(pcop)->r = allocRegByName(name, 1);
2127 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2128 pcop->type = PCOR(pcop)->r->pc_type;
2129 pcop->name = PCOR(pcop)->r->name;
2134 /*-----------------------------------------------------------------*/
2135 /*-----------------------------------------------------------------*/
2137 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2144 pcop = newpCodeOpBit(name, -1,0);
2148 pcop = newpCodeOpLit(-1);
2152 pcop = newpCodeOpLabel(NULL,-1);
2155 pcop = newpCodeOpReg(-1);
2159 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2162 pcop->name = Safe_strdup(name);
2170 /*-----------------------------------------------------------------*/
2171 /*-----------------------------------------------------------------*/
2172 void pCodeConstString(char *name, char *value)
2176 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2181 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2185 sprintf(buffer,"; %s = %s",name,value);
2187 addpCode2pBlock(pb,newpCodeCharP(buffer));
2188 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2191 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2197 /*-----------------------------------------------------------------*/
2198 /*-----------------------------------------------------------------*/
2199 void pCodeReadCodeTable(void)
2203 fprintf(stderr, " %s\n",__FUNCTION__);
2205 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2209 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2210 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2211 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2212 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2214 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2215 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2216 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2217 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2222 /*-----------------------------------------------------------------*/
2223 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2224 /*-----------------------------------------------------------------*/
2225 void addpCode2pBlock(pBlock *pb, pCode *pc)
2232 /* If this is the first pcode to be added to a block that
2233 * was initialized with a NULL pcode, then go ahead and
2234 * make this pcode the head and tail */
2235 pb->pcHead = pb->pcTail = pc;
2238 pb->pcTail->next = pc;
2240 pc->prev = pb->pcTail;
2247 /*-----------------------------------------------------------------*/
2248 /* addpBlock - place a pBlock into the pFile */
2249 /*-----------------------------------------------------------------*/
2250 void addpBlock(pBlock *pb)
2252 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2255 /* First time called, we'll pass through here. */
2256 //_ALLOC(the_pFile,sizeof(pFile));
2257 the_pFile = Safe_calloc(1,sizeof(pFile));
2258 the_pFile->pbHead = the_pFile->pbTail = pb;
2259 the_pFile->functions = NULL;
2263 the_pFile->pbTail->next = pb;
2264 pb->prev = the_pFile->pbTail;
2266 the_pFile->pbTail = pb;
2269 /*-----------------------------------------------------------------*/
2270 /* removepBlock - remove a pBlock from the pFile */
2271 /*-----------------------------------------------------------------*/
2272 void removepBlock(pBlock *pb)
2280 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2282 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2285 if(pbs == the_pFile->pbHead)
2286 the_pFile->pbHead = pbs->next;
2288 if (pbs == the_pFile->pbTail)
2289 the_pFile->pbTail = pbs->prev;
2292 pbs->next->prev = pbs->prev;
2295 pbs->prev->next = pbs->next;
2302 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2306 /*-----------------------------------------------------------------*/
2307 /* printpCode - write the contents of a pCode to a file */
2308 /*-----------------------------------------------------------------*/
2309 void printpCode(FILE *of, pCode *pc)
2320 fprintf(of,"warning - unable to print pCode\n");
2323 /*-----------------------------------------------------------------*/
2324 /* printpBlock - write the contents of a pBlock to a file */
2325 /*-----------------------------------------------------------------*/
2326 void printpBlock(FILE *of, pBlock *pb)
2336 for(pc = pb->pcHead; pc; pc = pc->next)
2341 /*-----------------------------------------------------------------*/
2343 /* pCode processing */
2347 /*-----------------------------------------------------------------*/
2349 void unlinkpCode(pCode *pc)
2355 fprintf(stderr,"Unlinking: ");
2356 printpCode(stderr, pc);
2359 pc->prev->next = pc->next;
2361 pc->next->prev = pc->prev;
2363 pc->prev = pc->next = NULL;
2367 /*-----------------------------------------------------------------*/
2368 /*-----------------------------------------------------------------*/
2370 static void genericDestruct(pCode *pc)
2376 /* For instructions, tell the register (if there's one used)
2377 * that it's no longer needed */
2378 regs *reg = getRegFromInstruction(pc);
2380 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2383 /* Instead of deleting the memory used by this pCode, mark
2384 * the object as bad so that if there's a pointer to this pCode
2385 * dangling around somewhere then (hopefully) when the type is
2386 * checked we'll catch it.
2391 addpCode2pBlock(pb_dead_pcodes, pc);
2398 /*-----------------------------------------------------------------*/
2399 /*-----------------------------------------------------------------*/
2400 void pBlockRegs(FILE *of, pBlock *pb)
2405 r = setFirstItem(pb->tregisters);
2407 r = setNextItem(pb->tregisters);
2412 /*-----------------------------------------------------------------*/
2413 /*-----------------------------------------------------------------*/
2414 char *get_op(pCodeOp *pcop,char *buffer, int size)
2419 int use_buffer = 1; // copy the string to the passed buffer pointer
2424 use_buffer = 0; // Don't bother copying the string to the buffer.
2428 switch(pcop->type) {
2432 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2435 return PCOR(pcop)->r->name;
2438 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2441 SAFE_snprintf(&buffer,&size,"%s",r->name);
2451 if(PCOI(pcop)->_const) {
2453 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2454 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2457 8 * PCOI(pcop)->offset );
2459 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2462 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2463 SAFE_snprintf(&s,&size,"(%s + %d)",
2465 PCOI(pcop)->index );
2467 SAFE_snprintf(&s,&size,"%s",pcop->name);
2474 //size = sizeof(buffer);
2475 if( PCOR(pcop)->instance) {
2476 SAFE_snprintf(&s,&size,"(%s + %d)",
2478 PCOR(pcop)->instance );
2479 //fprintf(stderr,"PO_DIR %s\n",buffer);
2481 SAFE_snprintf(&s,&size,"%s",pcop->name);
2487 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2496 return "NO operand";
2500 /*-----------------------------------------------------------------*/
2501 /*-----------------------------------------------------------------*/
2502 static char *get_op_from_instruction( pCodeInstruction *pcc)
2506 return get_op(pcc->pcop,NULL,0);
2508 return ("ERROR Null: "__FUNCTION__);
2512 /*-----------------------------------------------------------------*/
2513 /*-----------------------------------------------------------------*/
2514 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2517 fprintf(of,"pcodeopprint- not implemented\n");
2520 /*-----------------------------------------------------------------*/
2521 /*-----------------------------------------------------------------*/
2522 char *pCode2str(char *str, int size, pCode *pc)
2530 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2532 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2534 if(PCI(pc)->isBitInst) {
2535 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2536 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2537 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2538 PCI(pc)->pcop->name ,
2539 PCI(pc)->pcop->name );
2541 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2542 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2543 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2544 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2546 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2547 //PCI(pc)->pcop->t.bit );
2550 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2551 if( PCI(pc)->num_ops == 2)
2552 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2554 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2557 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2559 if( PCI(pc)->num_ops == 2)
2560 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2568 /* assuming that comment ends with a \n */
2569 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2573 /* assuming that inline code ends with a \n */
2574 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2578 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2581 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2584 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2587 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2590 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2594 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2601 /*-----------------------------------------------------------------*/
2602 /* genericPrint - the contents of a pCode to a file */
2603 /*-----------------------------------------------------------------*/
2604 static void genericPrint(FILE *of, pCode *pc)
2612 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2616 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2620 // If the opcode has a label, print that first
2622 pBranch *pbl = PCI(pc)->label;
2623 while(pbl && pbl->pc) {
2624 if(pbl->pc->type == PC_LABEL)
2625 pCodePrintLabel(of, pbl->pc);
2631 genericPrint(of,PCODE(PCI(pc)->cline));
2636 pCode2str(str, 256, pc);
2638 fprintf(of,"%s",str);
2642 fprintf(of, "\t;key=%03x",pc->seq);
2644 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2649 pBranch *dpb = pc->to; // debug
2651 switch ( dpb->pc->type) {
2653 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2656 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2659 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2662 fprintf(of, "\t;flow");
2676 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2677 if(PCW(pc)->pci.label)
2678 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2680 if(PCW(pc)->operand) {
2681 fprintf(of,";\toperand ");
2682 pCodeOpPrint(of,PCW(pc)->operand );
2688 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2692 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2696 fprintf(of,"unknown pCode type %d\n",pc->type);
2701 /*-----------------------------------------------------------------*/
2702 /* pCodePrintFunction - prints function begin/end */
2703 /*-----------------------------------------------------------------*/
2705 static void pCodePrintFunction(FILE *of, pCode *pc)
2711 if( ((pCodeFunction *)pc)->modname)
2712 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2714 if(PCF(pc)->fname) {
2715 pBranch *exits = PCF(pc)->to;
2717 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2720 exits = exits->next;
2723 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2726 if((PCF(pc)->from &&
2727 PCF(pc)->from->pc->type == PC_FUNCTION &&
2728 PCF(PCF(pc)->from->pc)->fname) )
2729 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2731 fprintf(of,"; exit point [can't find entry point]\n");
2734 /*-----------------------------------------------------------------*/
2735 /* pCodePrintLabel - prints label */
2736 /*-----------------------------------------------------------------*/
2738 static void pCodePrintLabel(FILE *of, pCode *pc)
2745 fprintf(of,"%s\n",PCL(pc)->label);
2746 else if (PCL(pc)->key >=0)
2747 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2749 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2752 /*-----------------------------------------------------------------*/
2753 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2754 /* remove it if it is found. */
2755 /*-----------------------------------------------------------------*/
2756 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2763 if(pcl->type == PC_OPCODE)
2764 b = PCI(pcl)->label;
2766 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2771 //fprintf (stderr, "%s \n",__FUNCTION__);
2772 //pcl->print(stderr,pcl);
2773 //pc->print(stderr,pc);
2776 //fprintf (stderr, "found label\n");
2780 bprev->next = b->next; /* Not first pCode in chain */
2784 PCI(pcl)->label = b->next; /* First pCode in chain */
2787 return; /* A label can't occur more than once */
2795 /*-----------------------------------------------------------------*/
2796 /*-----------------------------------------------------------------*/
2797 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2816 /*-----------------------------------------------------------------*/
2817 /* pBranchLink - given two pcodes, this function will link them */
2818 /* together through their pBranches */
2819 /*-----------------------------------------------------------------*/
2820 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2824 // Declare a new branch object for the 'from' pCode.
2826 //_ALLOC(b,sizeof(pBranch));
2827 b = Safe_calloc(1,sizeof(pBranch));
2828 b->pc = PCODE(t); // The link to the 'to' pCode.
2831 f->to = pBranchAppend(f->to,b);
2833 // Now do the same for the 'to' pCode.
2835 //_ALLOC(b,sizeof(pBranch));
2836 b = Safe_calloc(1,sizeof(pBranch));
2840 t->from = pBranchAppend(t->from,b);
2845 /*-----------------------------------------------------------------*/
2846 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2848 /*-----------------------------------------------------------------*/
2849 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2862 /*-----------------------------------------------------------------*/
2863 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2864 /*-----------------------------------------------------------------*/
2865 static void pCodeUnlink(pCode *pc)
2870 if(!pc->prev || !pc->next) {
2871 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2875 /* first remove the pCode from the chain */
2876 pc->prev->next = pc->next;
2877 pc->next->prev = pc->prev;
2879 /* Now for the hard part... */
2881 /* Remove the branches */
2885 pc1 = pb1->pc; /* Get the pCode that branches to the
2886 * one we're unlinking */
2888 /* search for the link back to this pCode (the one we're
2890 if(pb2 = pBranchFind(pc1->to,pc)) {
2891 pb2->pc = pc->to->pc; // make the replacement
2893 /* if the pCode we're unlinking contains multiple 'to'
2894 * branches (e.g. this a skip instruction) then we need
2895 * to copy these extra branches to the chain. */
2897 pBranchAppend(pb2, pc->to->next);
2906 /*-----------------------------------------------------------------*/
2907 /*-----------------------------------------------------------------*/
2909 static void genericAnalyze(pCode *pc)
2919 // Go through the pCodes that are in pCode chain and link
2920 // them together through the pBranches. Note, the pCodes
2921 // are linked together as a contiguous stream like the
2922 // assembly source code lines. The linking here mimics this
2923 // except that comments are not linked in.
2925 pCode *npc = pc->next;
2927 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2928 pBranchLink(pc,npc);
2933 /* reached the end of the pcode chain without finding
2934 * an instruction we could link to. */
2938 fprintf(stderr,"analyze PC_FLOW\n");
2942 fprintf(stderr,,";A bad pCode is being used\n");
2948 /*-----------------------------------------------------------------*/
2949 /*-----------------------------------------------------------------*/
2950 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2954 if(pc->type == PC_LABEL) {
2955 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2958 if(pc->type == PC_OPCODE) {
2959 pbr = PCI(pc)->label;
2961 if(pbr->pc->type == PC_LABEL) {
2962 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2972 /*-----------------------------------------------------------------*/
2973 /*-----------------------------------------------------------------*/
2974 int checkLabel(pCode *pc)
2978 if(pc && isPCI(pc)) {
2979 pbr = PCI(pc)->label;
2981 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2991 /*-----------------------------------------------------------------*/
2992 /* findLabelinpBlock - Search the pCode for a particular label */
2993 /*-----------------------------------------------------------------*/
2994 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3001 for(pc = pb->pcHead; pc; pc = pc->next)
3002 if(compareLabel(pc,pcop_label))
3008 /*-----------------------------------------------------------------*/
3009 /* findLabel - Search the pCode for a particular label */
3010 /*-----------------------------------------------------------------*/
3011 pCode * findLabel(pCodeOpLabel *pcop_label)
3019 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3020 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3024 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3028 /*-----------------------------------------------------------------*/
3029 /* findNextpCode - given a pCode, find the next of type 'pct' */
3030 /* in the linked list */
3031 /*-----------------------------------------------------------------*/
3032 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3045 /*-----------------------------------------------------------------*/
3046 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3047 /* in the linked list */
3048 /*-----------------------------------------------------------------*/
3049 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3061 /*-----------------------------------------------------------------*/
3062 /* findNextInstruction - given a pCode, find the next instruction */
3063 /* in the linked list */
3064 /*-----------------------------------------------------------------*/
3065 pCode * findNextInstruction(pCode *pci)
3070 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3074 fprintf(stderr,"findNextInstruction: ");
3075 printpCode(stderr, pc);
3080 //fprintf(stderr,"Couldn't find instruction\n");
3084 /*-----------------------------------------------------------------*/
3085 /* findNextInstruction - given a pCode, find the next instruction */
3086 /* in the linked list */
3087 /*-----------------------------------------------------------------*/
3088 pCode * findPrevInstruction(pCode *pci)
3090 return findPrevpCode(pci, PC_OPCODE);
3093 /*-----------------------------------------------------------------*/
3094 /* findFunctionEnd - given a pCode find the end of the function */
3095 /* that contains it */
3096 /*-----------------------------------------------------------------*/
3097 pCode * findFunctionEnd(pCode *pc)
3101 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3107 fprintf(stderr,"Couldn't find function end\n");
3112 /*-----------------------------------------------------------------*/
3113 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3114 /* instruction with which it is associated. */
3115 /*-----------------------------------------------------------------*/
3116 static void AnalyzeLabel(pCode *pc)
3125 static void AnalyzeGOTO(pCode *pc)
3128 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3132 static void AnalyzeSKIP(pCode *pc)
3135 pBranchLink(pc,findNextInstruction(pc->next));
3136 pBranchLink(pc,findNextInstruction(pc->next->next));
3140 static void AnalyzeRETURN(pCode *pc)
3143 // branch_link(pc,findFunctionEnd(pc->next));
3149 /*-----------------------------------------------------------------*/
3150 /*-----------------------------------------------------------------*/
3151 regs * getRegFromInstruction(pCode *pc)
3157 PCI(pc)->num_ops == 0 )
3160 switch(PCI(pc)->pcop->type) {
3163 return PCOR(PCI(pc)->pcop)->r;
3165 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3169 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3170 return PCOR(PCI(pc)->pcop)->r;
3173 if(PCOI(PCI(pc)->pcop)->r)
3174 return (PCOI(PCI(pc)->pcop)->r);
3176 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3177 return dirregWithName(PCI(pc)->pcop->name);
3178 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3181 return PCOR(PCI(pc)->pcop)->r;
3184 //fprintf(stderr, "getRegFromInstruction - dir\n");
3185 return PCOR(PCI(pc)->pcop)->r;
3187 //fprintf(stderr, "getRegFromInstruction - literal\n");
3191 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3192 //genericPrint(stderr, pc);
3200 /*-----------------------------------------------------------------*/
3201 /*-----------------------------------------------------------------*/
3203 void AnalyzepBlock(pBlock *pb)
3210 /* Find all of the registers used in this pBlock
3211 * by looking at each instruction and examining it's
3214 for(pc = pb->pcHead; pc; pc = pc->next) {
3216 /* Is this an instruction with operands? */
3217 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3219 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3221 /* Loop through all of the registers declared so far in
3222 this block and see if we find this one there */
3224 regs *r = setFirstItem(pb->tregisters);
3227 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3228 PCOR(PCI(pc)->pcop)->r = r;
3231 r = setNextItem(pb->tregisters);
3235 /* register wasn't found */
3236 //r = Safe_calloc(1, sizeof(regs));
3237 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3238 //addSet(&pb->tregisters, r);
3239 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3240 //PCOR(PCI(pc)->pcop)->r = r;
3241 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3243 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3246 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3247 if(PCOR(PCI(pc)->pcop)->r) {
3248 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3249 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3251 if(PCI(pc)->pcop->name)
3252 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3254 fprintf(stderr,"ERROR: NULL register\n");
3263 /*-----------------------------------------------------------------*/
3265 /*-----------------------------------------------------------------*/
3266 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3268 void InsertpFlow(pCode *pc, pCode **pflow)
3271 PCFL(*pflow)->end = pc;
3273 if(!pc || !pc->next)
3276 *pflow = newpCodeFlow();
3277 pCodeInsertAfter(pc, *pflow);
3280 /*-----------------------------------------------------------------*/
3281 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3282 /* the flow blocks. */
3284 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3285 * point the instruction flow changes.
3287 /*-----------------------------------------------------------------*/
3288 void BuildFlow(pBlock *pb)
3291 pCode *last_pci=NULL;
3298 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3299 /* Insert a pCodeFlow object at the beginning of a pBlock */
3301 InsertpFlow(pb->pcHead, &pflow);
3303 //pflow = newpCodeFlow(); /* Create a new Flow object */
3304 //pflow->next = pb->pcHead; /* Make the current head the next object */
3305 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3306 //pb->pcHead = pflow; /* Make the Flow object the head */
3309 for( pc = findNextInstruction(pb->pcHead);
3311 pc=findNextInstruction(pc)) {
3314 PCI(pc)->pcflow = PCFL(pflow);
3316 //fprintf(stderr," build: ");
3317 //pflow->print(stderr,pflow);
3319 if( PCI(pc)->isSkip) {
3321 /* The two instructions immediately following this one
3322 * mark the beginning of a new flow segment */
3324 while(pc && PCI(pc)->isSkip) {
3326 PCI(pc)->pcflow = PCFL(pflow);
3330 InsertpFlow(pc, &pflow);
3331 pc=findNextInstruction(pc->next);
3339 PCI(pc)->pcflow = PCFL(pflow);
3341 InsertpFlow(pc, &pflow);
3343 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3345 InsertpFlow(pc, &pflow);
3348 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3350 /* This instruction marks the beginning of a
3351 * new flow segment */
3355 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3357 PCI(pc)->pcflow = PCFL(pflow);
3364 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3366 PCFL(pflow)->end = pb->pcTail;
3369 /*-------------------------------------------------------------------*/
3370 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3371 /* the flow blocks. */
3373 * unBuildFlow removes pCodeFlow objects from a pCode chain
3375 /*-----------------------------------------------------------------*/
3376 void unBuildFlow(pBlock *pb)
3391 if(PCI(pc)->pcflow) {
3392 //free(PCI(pc)->pcflow);
3393 PCI(pc)->pcflow = NULL;
3396 } else if(isPCFL(pc) )
3405 /*-----------------------------------------------------------------*/
3406 /*-----------------------------------------------------------------*/
3407 void dumpCond(int cond)
3410 static char *pcc_str[] = {
3424 int ncond = sizeof(pcc_str) / sizeof(char *);
3427 fprintf(stderr, "0x%04X\n",cond);
3429 for(i=0,j=1; i<ncond; i++, j<<=1)
3431 fprintf(stderr, " %s\n",pcc_str[i]);
3435 /*-----------------------------------------------------------------*/
3436 /*-----------------------------------------------------------------*/
3437 void FlowStats(pCodeFlow *pcflow)
3445 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3447 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3450 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3455 fprintf(stderr, " FlowStats inCond: ");
3456 dumpCond(pcflow->inCond);
3457 fprintf(stderr, " FlowStats outCond: ");
3458 dumpCond(pcflow->outCond);
3462 /*-----------------------------------------------------------------*
3463 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3464 * if it affects the banking bits.
3466 * return: -1 == Banking bits are unaffected by this pCode.
3468 * return: > 0 == Banking bits are affected.
3470 * If the banking bits are affected, then the returned value describes
3471 * which bits are affected and how they're affected. The lower half
3472 * of the integer maps to the bits that are affected, the upper half
3473 * to whether they're set or cleared.
3475 *-----------------------------------------------------------------*/
3476 #define SET_BANK_BIT (1 << 16)
3477 #define CLR_BANK_BIT 0
3479 int isBankInstruction(pCode *pc)
3487 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3489 /* Check to see if the register banks are changing */
3490 if(PCI(pc)->isModReg) {
3492 pCodeOp *pcop = PCI(pc)->pcop;
3493 switch(PCI(pc)->op) {
3496 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3497 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3498 return SET_BANK_BIT | PIC_RP0_BIT;
3501 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3502 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3503 return CLR_BANK_BIT | PIC_RP0_BIT;
3508 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3509 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3510 return CLR_BANK_BIT | PIC_RP1_BIT;
3512 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3513 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3514 return CLR_BANK_BIT | PIC_RP1_BIT;
3518 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3519 //genericPrint(stderr, pc);
3530 /*-----------------------------------------------------------------*/
3531 /*-----------------------------------------------------------------*/
3532 void FillFlow(pCodeFlow *pcflow)
3541 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3543 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3546 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3553 isBankInstruction(pc);
3555 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3559 fprintf(stderr, " FillFlow - Bad end of flow\n");
3561 fprintf(stderr, " FillFlow - Ending flow with\n ");
3562 pc->print(stderr,pc);
3565 fprintf(stderr, " FillFlow inCond: ");
3566 dumpCond(pcflow->inCond);
3567 fprintf(stderr, " FillFlow outCond: ");
3568 dumpCond(pcflow->outCond);
3572 /*-----------------------------------------------------------------*/
3573 /*-----------------------------------------------------------------*/
3574 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3576 pCodeFlowLink *fromLink, *toLink;
3578 if(!from || !to || !to->pcflow || !from->pcflow)
3581 fromLink = newpCodeFlowLink(from->pcflow);
3582 toLink = newpCodeFlowLink(to->pcflow);
3584 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3585 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3589 /*-----------------------------------------------------------------*/
3590 /*-----------------------------------------------------------------*/
3591 void LinkFlow(pBlock *pb)
3597 //fprintf(stderr,"linkflow \n");
3599 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3601 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3604 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3606 //fprintf(stderr," link: ");
3607 //pcflow->print(stderr,pcflow);
3609 //FillFlow(PCFL(pcflow));
3611 pc = PCFL(pcflow)->end;
3613 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3614 if(isPCI_SKIP(pc)) {
3615 //fprintf(stderr, "ends with skip\n");
3616 //pc->print(stderr,pc);
3617 pct=findNextInstruction(pc->next);
3618 LinkFlow_pCode(PCI(pc),PCI(pct));
3619 pct=findNextInstruction(pct->next);
3620 LinkFlow_pCode(PCI(pc),PCI(pct));
3624 if(isPCI_BRANCH(pc)) {
3625 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3627 //fprintf(stderr, "ends with branch\n ");
3628 //pc->print(stderr,pc);
3630 if(!(pcol && isPCOLAB(pcol))) {
3631 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3632 pc->print(stderr,pc);
3633 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3638 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3639 LinkFlow_pCode(PCI(pc),PCI(pct));
3641 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3647 //fprintf(stderr, "ends with non-branching instruction:\n");
3648 //pc->print(stderr,pc);
3650 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3656 //fprintf(stderr, "ends with unknown\n");
3657 //pc->print(stderr,pc);
3661 //fprintf(stderr, "ends with nothing: ERROR\n");
3666 /*-----------------------------------------------------------------*/
3667 /*-----------------------------------------------------------------*/
3668 int isPCinFlow(pCode *pc, pCode *pcflow)
3674 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3677 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3683 /*-----------------------------------------------------------------*/
3684 /*-----------------------------------------------------------------*/
3685 void BanksUsedFlow2(pCode *pcflow)
3694 if(!isPCFL(pcflow)) {
3695 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3699 pc = findNextInstruction(pcflow->next);
3701 PCFL(pcflow)->lastBank = -1;
3703 while(isPCinFlow(pc,pcflow)) {
3705 int bank_selected = isBankInstruction(pc);
3707 //if(PCI(pc)->pcflow)
3708 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3710 if(bank_selected > 0) {
3711 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3713 /* This instruction is modifying banking bits before accessing registers */
3715 PCFL(pcflow)->firstBank = -1;
3717 if(PCFL(pcflow)->lastBank == -1)
3718 PCFL(pcflow)->lastBank = 0;
3720 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3721 if(bank_selected & SET_BANK_BIT)
3722 PCFL(pcflow)->lastBank |= bank;
3726 reg = getRegFromInstruction(pc);
3728 if(reg && !isREGinBank(reg, bank)) {
3729 int allbanks = REGallBanks(reg);
3731 PCFL(pcflow)->firstBank = allbanks;
3733 PCFL(pcflow)->lastBank = allbanks;
3740 pc = findNextInstruction(pc->next);
3743 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3744 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3749 /*-----------------------------------------------------------------*/
3750 /*-----------------------------------------------------------------*/
3751 void BanksUsedFlow(pBlock *pb)
3756 //pb->pcHead->print(stderr, pb->pcHead);
3758 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3759 //pcflow->print(stderr,pcflow);
3761 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3763 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3765 BanksUsedFlow2(pcflow);
3771 /*-----------------------------------------------------------------*/
3772 /*-----------------------------------------------------------------*/
3773 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3781 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3783 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3784 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3786 pCodeInsertAfter(pc->prev, new_pc);
3788 /* Move the label, if there is one */
3790 if(PCI(pc)->label) {
3791 PCI(new_pc)->label = PCI(pc)->label;
3792 PCI(pc)->label = NULL;
3795 /* The new instruction has the same pcflow block */
3796 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3799 /*-----------------------------------------------------------------*/
3800 /*-----------------------------------------------------------------*/
3801 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3812 pc = findNextInstruction(pcfl->pc.next);
3814 while(isPCinFlow(pc,PCODE(pcfl))) {
3817 reg = getRegFromInstruction(pc);
3820 fprintf(stderr, " %s ",reg->name);
3821 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3826 if(reg && REG_BANK(reg)!=cur_bank) {
3827 /* Examine the instruction before this one to make sure it is
3828 * not a skip type instruction */
3829 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3830 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3831 int b = cur_bank ^ REG_BANK(reg);
3833 //fprintf(stderr, "Cool! can switch banks\n");
3834 cur_bank = REG_BANK(reg);
3839 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3842 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3843 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3847 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3848 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3850 insertBankSwitch(pc, -1, -1);
3853 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3854 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3855 pCodeInsertAfter(pc->prev, new_pc);
3856 if(PCI(pc)->label) {
3857 PCI(new_pc)->label = PCI(pc)->label;
3858 PCI(pc)->label = NULL;
3862 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3863 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3864 pCodeInsertAfter(pc, new_pc);
3870 //fprintf(stderr, "Bummer can't switch banks\n");
3876 pc = findNextInstruction(pc->next);
3880 if(pcprev && cur_bank) {
3881 /* Brute force - make sure that we point to bank 0 at the
3882 * end of each flow block */
3883 new_pc = newpCode(POC_BCF,
3884 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3885 pCodeInsertAfter(pcprev, new_pc);
3891 /*-----------------------------------------------------------------*/
3892 /*int compareBankFlow - compare the banking requirements between */
3894 /*-----------------------------------------------------------------*/
3895 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3898 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3901 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3904 if(pcflow->firstBank == -1)
3908 if(pcflowLink->pcflow->firstBank == -1) {
3909 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3910 pcflowLink->pcflow->to :
3911 pcflowLink->pcflow->from);
3912 return compareBankFlow(pcflow, pctl, toORfrom);
3916 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3919 pcflowLink->bank_conflict++;
3920 pcflowLink->pcflow->FromConflicts++;
3921 pcflow->ToConflicts++;
3924 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3927 pcflowLink->bank_conflict++;
3928 pcflowLink->pcflow->ToConflicts++;
3929 pcflow->FromConflicts++;
3933 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3934 pcflowLink->pcflow->pc.seq,
3935 pcflowLink->pcflow->FromConflicts,
3936 pcflowLink->pcflow->ToConflicts);
3941 /*-----------------------------------------------------------------*/
3942 /*-----------------------------------------------------------------*/
3943 void FixBankFlow(pBlock *pb)
3947 pCodeFlowLink *pcfl;
3949 pCode *pcflow_max_To=NULL;
3950 pCode *pcflow_max_From=NULL;
3951 int max_ToConflicts=0;
3952 int max_FromConflicts=0;
3954 //fprintf(stderr,"Fix Bank flow \n");
3955 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3959 First loop through all of the flow objects in this pcode block
3960 and fix the ones that have banking conflicts between the
3964 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3966 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3968 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3970 if(!isPCFL(pcflow)) {
3971 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3975 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3976 PCFL(pcflow)->firstBank >= 0 &&
3977 PCFL(pcflow)->lastBank >= 0 ) {
3979 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3980 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3982 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3983 BanksUsedFlow2(pcflow);
3988 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3990 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3992 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3997 if(!isPCFL(pcflow)) {
3998 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4002 PCFL(pcflow)->FromConflicts = 0;
4003 PCFL(pcflow)->ToConflicts = 0;
4008 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4009 pcfl = setFirstItem(PCFL(pcflow)->from);
4012 pc = PCODE(pcfl->pcflow);
4015 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4016 pc->print(stderr,pc);
4019 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4022 pcfl=setNextItem(PCFL(pcflow)->from);
4025 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4026 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4028 FixRegisterBankingInFlow(PCFL(pcflow),0);
4029 BanksUsedFlow2(pcflow);
4031 continue; /* Don't need to check the flow from here - it's already been fixed */
4038 pcfl = setFirstItem(PCFL(pcflow)->to);
4041 pc = PCODE(pcfl->pcflow);
4043 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4044 pc->print(stderr,pc);
4047 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4050 pcfl=setNextItem(PCFL(pcflow)->to);
4053 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4054 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4056 FixRegisterBankingInFlow(PCFL(pcflow),0);
4057 BanksUsedFlow2(pcflow);
4062 Loop through the flow objects again and find the ones with the
4066 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4068 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4070 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4071 pcflow_max_To = pcflow;
4073 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4074 pcflow_max_From = pcflow;
4078 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4079 PCFL(pcflow_max_To)->pc.seq,
4080 PCFL(pcflow_max_To)->ToConflicts);
4083 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4084 PCFL(pcflow_max_From)->pc.seq,
4085 PCFL(pcflow_max_From)->FromConflicts);
4089 /*-----------------------------------------------------------------*/
4090 /*-----------------------------------------------------------------*/
4091 void DumpFlow(pBlock *pb)
4095 pCodeFlowLink *pcfl;
4098 fprintf(stderr,"Dump flow \n");
4099 pb->pcHead->print(stderr, pb->pcHead);
4101 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4102 pcflow->print(stderr,pcflow);
4104 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4106 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4108 if(!isPCFL(pcflow)) {
4109 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4112 fprintf(stderr,"dumping: ");
4113 pcflow->print(stderr,pcflow);
4114 FlowStats(PCFL(pcflow));
4116 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4118 pc = PCODE(pcfl->pcflow);
4120 fprintf(stderr, " from seq %d:\n",pc->seq);
4122 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4123 pc->print(stderr,pc);
4128 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4130 pc = PCODE(pcfl->pcflow);
4132 fprintf(stderr, " to seq %d:\n",pc->seq);
4134 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4135 pc->print(stderr,pc);
4144 /*-----------------------------------------------------------------*/
4145 /*-----------------------------------------------------------------*/
4146 int OptimizepBlock(pBlock *pb)
4151 if(!pb || !peepOptimizing)
4154 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4156 for(pc = pb->pcHead; pc; pc = pc->next)
4157 matches += pCodePeepMatchRule(pc);
4160 pc = findNextInstruction(pb->pcHead);
4168 if(pCodePeepMatchRule(pc)) {
4173 pc = findNextInstruction(pcprev->next);
4175 pc = findNextInstruction(pb->pcHead);
4177 pc = findNextInstruction(pc->next);
4181 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4186 /*-----------------------------------------------------------------*/
4187 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4188 /*-----------------------------------------------------------------*/
4189 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4193 for(pc = pcs; pc; pc = pc->next) {
4195 if((pc->type == PC_OPCODE) &&
4197 (PCI(pc)->pcop->type == PO_LABEL) &&
4198 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4206 /*-----------------------------------------------------------------*/
4207 /*-----------------------------------------------------------------*/
4208 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4213 (PCI(pc)->pcop->type == PO_LABEL)) {
4215 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4217 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4219 free(pcol->pcop.name);
4221 sprintf(buffer,"_%05d_DS_",pcl->key);
4223 pcol->pcop.name = Safe_strdup(buffer);
4224 pcol->key = pcl->key;
4225 //pc->print(stderr,pc);
4232 /*-----------------------------------------------------------------*/
4233 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4234 /* pCode chain if they're not used. */
4235 /*-----------------------------------------------------------------*/
4236 void pBlockRemoveUnusedLabels(pBlock *pb)
4238 pCode *pc; pCodeLabel *pcl;
4243 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4245 pBranch *pbr = PCI(pc)->label;
4246 if(pbr && pbr->next) {
4247 pCode *pcd = pb->pcHead;
4249 //fprintf(stderr, "multiple labels\n");
4250 //pc->print(stderr,pc);
4255 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4256 //fprintf(stderr,"Used by:\n");
4257 //pcd->print(stderr,pcd);
4259 exchangeLabels(PCL(pbr->pc),pcd);
4268 for(pc = pb->pcHead; pc; pc = pc->next) {
4270 if(isPCL(pc)) // pc->type == PC_LABEL)
4272 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4273 pcl = PCL(PCI(pc)->label->pc);
4276 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4278 /* This pCode is a label, so search the pBlock to see if anyone
4281 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4282 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4283 /* Couldn't find an instruction that refers to this label
4284 * So, unlink the pCode label from it's pCode chain
4285 * and destroy the label */
4286 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4288 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4289 if(pc->type == PC_LABEL) {
4291 pCodeLabelDestruct(pc);
4293 unlinkpCodeFromBranch(pc, PCODE(pcl));
4294 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4305 /*-----------------------------------------------------------------*/
4306 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4307 /* chain and put them into pBranches that are */
4308 /* associated with the appropriate pCode */
4310 /*-----------------------------------------------------------------*/
4311 void pBlockMergeLabels(pBlock *pb)
4314 pCode *pc, *pcnext=NULL;
4319 /* First, Try to remove any unused labels */
4320 //pBlockRemoveUnusedLabels(pb);
4322 /* Now loop through the pBlock and merge the labels with the opcodes */
4325 // for(pc = pb->pcHead; pc; pc = pc->next) {
4328 pCode *pcn = pc->next;
4330 if(pc->type == PC_LABEL) {
4332 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4333 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4334 if((pcnext = findNextInstruction(pc) )) {
4336 // Unlink the pCode label from it's pCode chain
4339 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4340 // And link it into the instruction's pBranch labels. (Note, since
4341 // it's possible to have multiple labels associated with one instruction
4342 // we must provide a means to accomodate the additional labels. Thus
4343 // the labels are placed into the singly-linked list "label" as
4344 // opposed to being a single member of the pCodeInstruction.)
4346 //_ALLOC(pbr,sizeof(pBranch));
4347 pbr = Safe_calloc(1,sizeof(pBranch));
4351 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4354 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4356 } else if(pc->type == PC_CSOURCE) {
4358 /* merge the source line symbolic info into the next instruction */
4359 if((pcnext = findNextInstruction(pc) )) {
4361 // Unlink the pCode label from it's pCode chain
4363 PCI(pcnext)->cline = PCCS(pc);
4364 //fprintf(stderr, "merging CSRC\n");
4365 //genericPrint(stderr,pcnext);
4371 pBlockRemoveUnusedLabels(pb);
4375 /*-----------------------------------------------------------------*/
4376 /*-----------------------------------------------------------------*/
4377 int OptimizepCode(char dbName)
4379 #define MAX_PASSES 4
4388 DFPRINTF((stderr," Optimizing pCode\n"));
4392 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4393 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4394 matches += OptimizepBlock(pb);
4397 while(matches && ++passes < MAX_PASSES);
4402 /*-----------------------------------------------------------------*/
4403 /* popCopyGPR2Bit - copy a pcode operator */
4404 /*-----------------------------------------------------------------*/
4406 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4410 pcop = newpCodeOpBit(pc->name, bitval, 0);
4412 if( !( (pcop->type == PO_LABEL) ||
4413 (pcop->type == PO_LITERAL) ||
4414 (pcop->type == PO_STR) ))
4415 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4423 /*-----------------------------------------------------------------*/
4424 /*-----------------------------------------------------------------*/
4425 int InstructionRegBank(pCode *pc)
4429 if( (reg = getRegFromInstruction(pc)) == NULL)
4432 return REG_BANK(reg);
4437 /*-----------------------------------------------------------------*/
4438 /*-----------------------------------------------------------------*/
4439 void FixRegisterBanking(pBlock *pb)
4451 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4452 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4455 /* loop through all of the flow blocks with in one pblock */
4457 //fprintf(stderr,"Register banking\n");
4460 /* at this point, pc should point to a PC_FLOW object */
4463 /* for each flow block, determine the register banking
4468 //genericPrint(stderr, pc);
4470 reg = getRegFromInstruction(pc);
4473 fprintf(stderr, " %s ",reg->name);
4474 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4478 if(reg && REG_BANK(reg)!=cur_bank) {
4479 /* Examine the instruction before this one to make sure it is
4480 * not a skip type instruction */
4481 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4482 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4483 int b = cur_bank ^ REG_BANK(reg);
4485 //fprintf(stderr, "Cool! can switch banks\n");
4486 cur_bank = REG_BANK(reg);
4488 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4489 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4490 pCodeInsertAfter(pc->prev, new_pc);
4491 if(PCI(pc)->label) {
4492 PCI(new_pc)->label = PCI(pc)->label;
4493 PCI(pc)->label = NULL;
4496 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4497 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4498 pCodeInsertAfter(pc, new_pc);
4504 //fprintf(stderr, "Bummer can't switch banks\n");
4512 // } while(pc && !(isPCFL(pc)));
4517 if(pcprev && cur_bank) {
4518 /* Brute force - make sure that we point to bank 0 at the
4519 * end of each flow block */
4520 new_pc = newpCode(POC_BCF,
4521 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4522 pCodeInsertAfter(pcprev, new_pc);
4528 void pBlockDestruct(pBlock *pb)
4539 /*-----------------------------------------------------------------*/
4540 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4541 /* name dbName and combine them */
4542 /* into one block */
4543 /*-----------------------------------------------------------------*/
4544 void mergepBlocks(char dbName)
4547 pBlock *pb, *pbmerged = NULL,*pbn;
4549 pb = the_pFile->pbHead;
4551 //fprintf(stderr," merging blocks named %c\n",dbName);
4555 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4556 if( getpBlock_dbName(pb) == dbName) {
4558 //fprintf(stderr," merged block %c\n",dbName);
4563 addpCode2pBlock(pbmerged, pb->pcHead);
4564 /* addpCode2pBlock doesn't handle the tail: */
4565 pbmerged->pcTail = pb->pcTail;
4567 pb->prev->next = pbn;
4569 pbn->prev = pb->prev;
4574 //printpBlock(stderr, pbmerged);
4581 /*-----------------------------------------------------------------*/
4582 /* AnalyzeFlow - Examine the flow of the code and optimize */
4584 /* level 0 == minimal optimization */
4585 /* optimize registers that are used only by two instructions */
4586 /* level 1 == maximal optimization */
4587 /* optimize by looking at pairs of instructions that use the */
4589 /*-----------------------------------------------------------------*/
4591 void AnalyzeFlow(int level)
4593 static int times_called=0;
4601 /* if this is not the first time this function has been called,
4602 then clean up old flow information */
4603 if(times_called++) {
4604 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4607 RegsUnMapLiveRanges();
4613 /* Phase 2 - Flow Analysis - Register Banking
4615 * In this phase, the individual flow blocks are examined
4616 * and register banking is fixed.
4619 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4620 //FixRegisterBanking(pb);
4622 /* Phase 2 - Flow Analysis
4624 * In this phase, the pCode is partition into pCodeFlow
4625 * blocks. The flow blocks mark the points where a continuous
4626 * stream of instructions changes flow (e.g. because of
4627 * a call or goto or whatever).
4630 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4634 /* Phase 2 - Flow Analysis - linking flow blocks
4636 * In this phase, the individual flow blocks are examined
4637 * to determine their order of excution.
4640 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4643 /* Phase 3 - Flow Analysis - Flow Tree
4645 * In this phase, the individual flow blocks are examined
4646 * to determine their order of excution.
4649 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4653 /* Phase x - Flow Analysis - Used Banks
4655 * In this phase, the individual flow blocks are examined
4656 * to determine the Register Banks they use
4659 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4663 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4664 pCodeRegMapLiveRanges(pb);
4666 RemoveUnusedRegisters();
4668 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4669 pCodeRegOptimizeRegUsage(level);
4675 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4679 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4681 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4682 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4683 pcflow = pcflow->next) {
4685 FillFlow(PCFL(pcflow));
4690 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4692 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4693 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4694 pcflow = pcflow->next) {
4696 FlowStats(PCFL(pcflow));
4702 /*-----------------------------------------------------------------*/
4703 /* AnalyzeBanking - Called after the memory addresses have been */
4704 /* assigned to the registers. */
4706 /*-----------------------------------------------------------------*/
4708 void AnalyzeBanking(void)
4712 /* Phase x - Flow Analysis - Used Banks
4714 * In this phase, the individual flow blocks are examined
4715 * to determine the Register Banks they use
4721 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4723 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4724 FixRegisterBanking(pb);
4728 /*-----------------------------------------------------------------*/
4729 /* buildCallTree - look at the flow and extract all of the calls */
4731 /*-----------------------------------------------------------------*/
4732 set *register_usage(pBlock *pb);
4734 void buildCallTree(void )
4745 /* Now build the call tree.
4746 First we examine all of the pCodes for functions.
4747 Keep in mind that the function boundaries coincide
4748 with pBlock boundaries.
4750 The algorithm goes something like this:
4751 We have two nested loops. The outer loop iterates
4752 through all of the pBlocks/functions. The inner
4753 loop iterates through all of the pCodes for
4754 a given pBlock. When we begin iterating through
4755 a pBlock, the variable pc_fstart, pCode of the start
4756 of a function, is cleared. We then search for pCodes
4757 of type PC_FUNCTION. When one is encountered, we
4758 initialize pc_fstart to this and at the same time
4759 associate a new pBranch object that signifies a
4760 branch entry. If a return is found, then this signifies
4761 a function exit point. We'll link the pCodes of these
4762 returns to the matching pc_fstart.
4764 When we're done, a doubly linked list of pBranches
4765 will exist. The head of this list is stored in
4766 `the_pFile', which is the meta structure for all
4767 of the pCode. Look at the printCallTree function
4768 on how the pBranches are linked together.
4771 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4772 pCode *pc_fstart=NULL;
4773 for(pc = pb->pcHead; pc; pc = pc->next) {
4775 if (PCF(pc)->fname) {
4777 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4778 //fprintf(stderr," found main \n");
4779 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4783 pbr = Safe_calloc(1,sizeof(pBranch));
4784 pbr->pc = pc_fstart = pc;
4787 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4789 // Here's a better way of doing the same:
4790 addSet(&pb->function_entries, pc);
4793 // Found an exit point in a function, e.g. return
4794 // (Note, there may be more than one return per function)
4796 pBranchLink(PCF(pc_fstart), PCF(pc));
4798 addSet(&pb->function_exits, pc);
4800 } else if(isCALL(pc)) {
4801 addSet(&pb->function_calls,pc);
4806 /* Re-allocate the registers so that there are no collisions
4807 * between local variables when one function call another */
4810 // pic14_deallocateAllRegs();
4812 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4819 /*-----------------------------------------------------------------*/
4820 /* AnalyzepCode - parse the pCode that has been generated and form */
4821 /* all of the logical connections. */
4823 /* Essentially what's done here is that the pCode flow is */
4825 /*-----------------------------------------------------------------*/
4827 void AnalyzepCode(char dbName)
4838 /* Phase 1 - Register allocation and peep hole optimization
4840 * The first part of the analysis is to determine the registers
4841 * that are used in the pCode. Once that is done, the peep rules
4842 * are applied to the code. We continue to loop until no more
4843 * peep rule optimizations are found (or until we exceed the
4844 * MAX_PASSES threshold).
4846 * When done, the required registers will be determined.
4852 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4853 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4855 /* First, merge the labels with the instructions */
4856 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4857 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4859 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4860 //fprintf(stderr," analyze and merging block %c\n",dbName);
4861 pBlockMergeLabels(pb);
4864 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4868 changes = OptimizepCode(dbName);
4870 } while(changes && (i++ < MAX_PASSES));
4875 /*-----------------------------------------------------------------*/
4876 /* ispCodeFunction - returns true if *pc is the pCode of a */
4878 /*-----------------------------------------------------------------*/
4879 bool ispCodeFunction(pCode *pc)
4882 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4888 /*-----------------------------------------------------------------*/
4889 /* findFunction - Search for a function by name (given the name) */
4890 /* in the set of all functions that are in a pBlock */
4891 /* (note - I expect this to change because I'm planning to limit */
4892 /* pBlock's to just one function declaration */
4893 /*-----------------------------------------------------------------*/
4894 pCode *findFunction(char *fname)
4901 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4903 pc = setFirstItem(pb->function_entries);
4906 if((pc->type == PC_FUNCTION) &&
4908 (strcmp(fname, PCF(pc)->fname)==0))
4911 pc = setNextItem(pb->function_entries);
4919 void MarkUsedRegisters(set *regset)
4924 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4925 r2 = pic14_regWithIdx(r1->rIdx);
4931 void pBlockStats(FILE *of, pBlock *pb)
4937 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4939 // for now just print the first element of each set
4940 pc = setFirstItem(pb->function_entries);
4942 fprintf(of,";entry: ");
4945 pc = setFirstItem(pb->function_exits);
4947 fprintf(of,";has an exit\n");
4951 pc = setFirstItem(pb->function_calls);
4953 fprintf(of,";functions called:\n");
4956 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4957 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4959 pc = setNextItem(pb->function_calls);
4963 r = setFirstItem(pb->tregisters);
4965 int n = elementsInSet(pb->tregisters);
4967 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4970 fprintf(of,"; %s\n",r->name);
4971 r = setNextItem(pb->tregisters);
4976 /*-----------------------------------------------------------------*/
4977 /*-----------------------------------------------------------------*/
4979 static void sequencepCode(void)
4985 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4987 pb->seq = GpCodeSequenceNumber+1;
4989 for( pc = pb->pcHead; pc; pc = pc->next)
4990 pc->seq = ++GpCodeSequenceNumber;
4996 /*-----------------------------------------------------------------*/
4997 /*-----------------------------------------------------------------*/
4998 set *register_usage(pBlock *pb)
5001 set *registers=NULL;
5002 set *registersInCallPath = NULL;
5004 /* check recursion */
5006 pc = setFirstItem(pb->function_entries);
5013 if(pc->type != PC_FUNCTION)
5014 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5016 pc = setFirstItem(pb->function_calls);
5017 for( ; pc; pc = setNextItem(pb->function_calls)) {
5019 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5020 char *dest = get_op_from_instruction(PCI(pc));
5022 pcn = findFunction(dest);
5024 registersInCallPath = register_usage(pcn->pb);
5026 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5031 pBlockStats(stderr,pb); // debug
5034 // Mark the registers in this block as used.
5036 MarkUsedRegisters(pb->tregisters);
5037 if(registersInCallPath) {
5038 /* registers were used in the functions this pBlock has called */
5039 /* so now, we need to see if these collide with the ones we are */
5042 regs *r1,*r2, *newreg;
5044 DFPRINTF((stderr,"comparing registers\n"));
5046 r1 = setFirstItem(registersInCallPath);
5049 r2 = setFirstItem(pb->tregisters);
5051 while(r2 && (r1->type != REG_STK)) {
5053 if(r2->rIdx == r1->rIdx) {
5054 newreg = pic14_findFreeReg(REG_GPR);
5058 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5062 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5063 r1->rIdx, newreg->rIdx));
5064 r2->rIdx = newreg->rIdx;
5065 //if(r2->name) free(r2->name);
5067 r2->name = Safe_strdup(newreg->name);
5071 newreg->wasUsed = 1;
5073 r2 = setNextItem(pb->tregisters);
5076 r1 = setNextItem(registersInCallPath);
5079 /* Collisions have been resolved. Now free the registers in the call path */
5080 r1 = setFirstItem(registersInCallPath);
5082 if(r1->type != REG_STK) {
5083 newreg = pic14_regWithIdx(r1->rIdx);
5086 r1 = setNextItem(registersInCallPath);
5090 // MarkUsedRegisters(pb->registers);
5092 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5095 DFPRINTF((stderr,"returning regs\n"));
5097 DFPRINTF((stderr,"not returning regs\n"));
5099 DFPRINTF((stderr,"pBlock after register optim.\n"));
5100 pBlockStats(stderr,pb); // debug
5106 /*-----------------------------------------------------------------*/
5107 /* printCallTree - writes the call tree to a file */
5109 /*-----------------------------------------------------------------*/
5110 void pct2(FILE *of,pBlock *pb,int indent)
5114 // set *registersInCallPath = NULL;
5120 return; //recursion ?
5122 pc = setFirstItem(pb->function_entries);
5129 for(i=0;i<indent;i++) // Indentation
5132 if(pc->type == PC_FUNCTION)
5133 fprintf(of,"%s\n",PCF(pc)->fname);
5138 pc = setFirstItem(pb->function_calls);
5139 for( ; pc; pc = setNextItem(pb->function_calls)) {
5141 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5142 char *dest = get_op_from_instruction(PCI(pc));
5144 pcn = findFunction(dest);
5146 pct2(of,pcn->pb,indent+1);
5148 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5156 /*-----------------------------------------------------------------*/
5157 /* printCallTree - writes the call tree to a file */
5159 /*-----------------------------------------------------------------*/
5161 void printCallTree(FILE *of)
5173 fprintf(of, "\npBlock statistics\n");
5174 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5179 fprintf(of,"Call Tree\n");
5180 pbr = the_pFile->functions;
5184 if(!ispCodeFunction(pc))
5185 fprintf(of,"bug in call tree");
5188 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5190 while(pc->next && !ispCodeFunction(pc->next)) {
5192 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5193 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5201 fprintf(of,"\n**************\n\na better call tree\n");
5202 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5207 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5208 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5214 /*-----------------------------------------------------------------*/
5216 /*-----------------------------------------------------------------*/
5218 void InlineFunction(pBlock *pb)
5226 pc = setFirstItem(pb->function_calls);
5228 for( ; pc; pc = setNextItem(pb->function_calls)) {
5231 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5237 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5239 //fprintf(stderr,"Cool can inline:\n");
5240 //pcn->print(stderr,pcn);
5242 //fprintf(stderr,"recursive call Inline\n");
5243 InlineFunction(pcn->pb);
5244 //fprintf(stderr,"return from recursive call Inline\n");
5247 At this point, *pc points to a CALL mnemonic, and
5248 *pcn points to the function that is being called.
5250 To in-line this call, we need to remove the CALL
5251 and RETURN(s), and link the function pCode in with
5257 /* Remove the CALL */
5261 /* remove callee pBlock from the pBlock linked list */
5262 removepBlock(pcn->pb);
5270 /* Remove the Function pCode */
5271 pct = findNextInstruction(pcn->next);
5273 /* Link the function with the callee */
5274 pc->next = pcn->next;
5275 pcn->next->prev = pc;
5277 /* Convert the function name into a label */
5279 pbr = Safe_calloc(1,sizeof(pBranch));
5280 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5282 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5283 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5285 /* turn all of the return's except the last into goto's */
5286 /* check case for 2 instruction pBlocks */
5287 pce = findNextInstruction(pcn->next);
5289 pCode *pce_next = findNextInstruction(pce->next);
5291 if(pce_next == NULL) {
5292 /* found the last return */
5293 pCode *pc_call_next = findNextInstruction(pc_call->next);
5295 //fprintf(stderr,"found last return\n");
5296 //pce->print(stderr,pce);
5297 pce->prev->next = pc_call->next;
5298 pc_call->next->prev = pce->prev;
5299 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5309 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5315 /*-----------------------------------------------------------------*/
5317 /*-----------------------------------------------------------------*/
5319 void InlinepCode(void)
5328 if(!functionInlining)
5331 /* Loop through all of the function definitions and count the
5332 * number of times each one is called */
5333 //fprintf(stderr,"inlining %d\n",__LINE__);
5335 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5337 pc = setFirstItem(pb->function_calls);
5339 for( ; pc; pc = setNextItem(pb->function_calls)) {
5342 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5343 if(pcn && isPCF(pcn)) {
5344 PCF(pcn)->ncalled++;
5347 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5352 //fprintf(stderr,"inlining %d\n",__LINE__);
5354 /* Now, Loop through the function definitions again, but this
5355 * time inline those functions that have only been called once. */
5357 InlineFunction(the_pFile->pbHead);
5358 //fprintf(stderr,"inlining %d\n",__LINE__);
5360 for(pb = the_pFile->pbHead; pb; pb = pb->next)