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 int peepOptimizing = 1;
74 static int GpCodeSequenceNumber = 1;
75 static int GpcFlowSeq = 1;
77 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE))
78 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch)
79 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip)
80 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst)
81 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW))
82 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION))
83 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL))
84 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
86 /****************************************************************/
87 /* Forward declarations */
88 /****************************************************************/
90 static void unlinkPC(pCode *pc);
92 static void genericAnalyze(pCode *pc);
93 static void AnalyzeGOTO(pCode *pc);
94 static void AnalyzeSKIP(pCode *pc);
95 static void AnalyzeRETURN(pCode *pc);
98 static void genericDestruct(pCode *pc);
99 static void genericPrint(FILE *of,pCode *pc);
101 static void pCodePrintLabel(FILE *of, pCode *pc);
102 static void pCodePrintFunction(FILE *of, pCode *pc);
103 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
104 static char *get_op_from_instruction( pCodeInstruction *pcc);
105 char *get_op( pCodeOp *pcop);
106 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
107 int pCodePeepMatchRule(pCode *pc);
108 void pBlockStats(FILE *of, pBlock *pb);
109 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
111 pCodeInstruction pciADDWF = {
112 {PC_OPCODE, NULL, NULL, 0, NULL,
125 1,0, // dest, bit instruction
128 (PCC_W | PCC_REGISTER), // inCond
129 (PCC_REGISTER | PCC_Z) // outCond
132 pCodeInstruction pciADDFW = {
133 {PC_OPCODE, NULL, NULL, 0, NULL,
146 0,0, // dest, bit instruction
149 (PCC_W | PCC_REGISTER), // inCond
150 (PCC_W | PCC_Z) // outCond
153 pCodeInstruction pciADDLW = {
154 {PC_OPCODE, NULL, NULL, 0, NULL,
167 0,0, // dest, bit instruction
171 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
174 pCodeInstruction pciANDLW = {
175 {PC_OPCODE, NULL, NULL, 0, NULL,
188 0,0, // dest, bit instruction
192 (PCC_W | PCC_Z) // outCond
195 pCodeInstruction pciANDWF = {
196 {PC_OPCODE, NULL, NULL, 0, NULL,
209 1,0, // dest, bit instruction
212 (PCC_W | PCC_REGISTER), // inCond
213 (PCC_REGISTER | PCC_Z) // outCond
216 pCodeInstruction pciANDFW = {
217 {PC_OPCODE, NULL, NULL, 0, NULL,
230 0,0, // dest, bit instruction
233 (PCC_W | PCC_REGISTER), // inCond
234 (PCC_W | PCC_Z) // outCond
237 pCodeInstruction pciBCF = {
238 {PC_OPCODE, NULL, NULL, 0, NULL,
251 1,1, // dest, bit instruction
254 PCC_REGISTER, // inCond
255 PCC_REGISTER // outCond
258 pCodeInstruction pciBSF = {
259 {PC_OPCODE, NULL, NULL, 0, NULL,
272 1,1, // dest, bit instruction
275 PCC_REGISTER, // inCond
276 PCC_REGISTER // outCond
279 pCodeInstruction pciBTFSC = {
280 {PC_OPCODE, NULL, NULL, 0, NULL,
293 0,1, // dest, bit instruction
296 PCC_REGISTER, // inCond
300 pCodeInstruction pciBTFSS = {
301 {PC_OPCODE, NULL, NULL, 0, NULL,
314 0,1, // dest, bit instruction
317 PCC_REGISTER, // inCond
321 pCodeInstruction pciCALL = {
322 {PC_OPCODE, NULL, NULL, 0, NULL,
335 0,0, // dest, bit instruction
342 pCodeInstruction pciCOMF = {
343 {PC_OPCODE, NULL, NULL, 0, NULL,
356 1,0, // dest, bit instruction
359 PCC_REGISTER, // inCond
360 PCC_REGISTER // outCond
363 pCodeInstruction pciCOMFW = {
364 {PC_OPCODE, NULL, NULL, 0, NULL,
377 0,0, // dest, bit instruction
380 PCC_REGISTER, // inCond
384 pCodeInstruction pciCLRF = {
385 {PC_OPCODE, NULL, NULL, 0, NULL,
398 0,0, // dest, bit instruction
401 PCC_REGISTER, // inCond
402 PCC_REGISTER // outCond
405 pCodeInstruction pciCLRW = {
406 {PC_OPCODE, NULL, NULL, 0, NULL,
419 0,0, // dest, bit instruction
426 pCodeInstruction pciDECF = {
427 {PC_OPCODE, NULL, NULL, 0, NULL,
440 1,0, // dest, bit instruction
443 PCC_REGISTER, // inCond
444 PCC_REGISTER // outCond
447 pCodeInstruction pciDECFW = {
448 {PC_OPCODE, NULL, NULL, 0, NULL,
461 0,0, // dest, bit instruction
464 PCC_REGISTER, // inCond
468 pCodeInstruction pciDECFSZ = {
469 {PC_OPCODE, NULL, NULL, 0, NULL,
482 1,0, // dest, bit instruction
485 PCC_REGISTER, // inCond
486 PCC_REGISTER // outCond
489 pCodeInstruction pciDECFSZW = {
490 {PC_OPCODE, NULL, NULL, 0, NULL,
503 0,0, // dest, bit instruction
506 PCC_REGISTER, // inCond
510 pCodeInstruction pciGOTO = {
511 {PC_OPCODE, NULL, NULL, 0, NULL,
524 0,0, // dest, bit instruction
531 pCodeInstruction pciINCF = {
532 {PC_OPCODE, NULL, NULL, 0, NULL,
545 1,0, // dest, bit instruction
548 PCC_REGISTER, // inCond
549 PCC_REGISTER // outCond
552 pCodeInstruction pciINCFW = {
553 {PC_OPCODE, NULL, NULL, 0, NULL,
566 0,0, // dest, bit instruction
569 PCC_REGISTER, // inCond
573 pCodeInstruction pciINCFSZ = {
574 {PC_OPCODE, NULL, NULL, 0, NULL,
587 1,0, // dest, bit instruction
590 PCC_REGISTER, // inCond
591 PCC_REGISTER // outCond
594 pCodeInstruction pciINCFSZW = {
595 {PC_OPCODE, NULL, NULL, 0, NULL,
608 0,0, // dest, bit instruction
611 PCC_REGISTER, // inCond
615 pCodeInstruction pciIORWF = {
616 {PC_OPCODE, NULL, NULL, 0, NULL,
629 1,0, // dest, bit instruction
632 (PCC_W | PCC_REGISTER), // inCond
633 (PCC_REGISTER | PCC_Z) // outCond
636 pCodeInstruction pciIORFW = {
637 {PC_OPCODE, NULL, NULL, 0, NULL,
650 0,0, // dest, bit instruction
653 (PCC_W | PCC_REGISTER), // inCond
654 (PCC_W | PCC_Z) // outCond
657 pCodeInstruction pciIORLW = {
658 {PC_OPCODE, NULL, NULL, 0, NULL,
671 0,0, // dest, bit instruction
675 (PCC_W | PCC_Z) // outCond
678 pCodeInstruction pciMOVF = {
679 {PC_OPCODE, NULL, NULL, 0, NULL,
692 1,0, // dest, bit instruction
695 PCC_REGISTER, // inCond
699 pCodeInstruction pciMOVFW = {
700 {PC_OPCODE, NULL, NULL, 0, NULL,
713 0,0, // dest, bit instruction
716 PCC_REGISTER, // inCond
717 (PCC_W | PCC_Z) // outCond
720 pCodeInstruction pciMOVWF = {
721 {PC_OPCODE, NULL, NULL, 0, NULL,
734 0,0, // dest, bit instruction
738 PCC_REGISTER // outCond
741 pCodeInstruction pciMOVLW = {
742 {PC_OPCODE, NULL, NULL, 0, NULL,
755 0,0, // dest, bit instruction
762 pCodeInstruction pciNOP = {
763 {PC_OPCODE, NULL, NULL, 0, NULL,
775 0,0, // dest, bit instruction
782 pCodeInstruction pciRETFIE = {
783 {PC_OPCODE, NULL, NULL, 0, NULL,
796 0,0, // dest, bit instruction
800 PCC_NONE // outCond (not true... affects the GIE bit too)
803 pCodeInstruction pciRETLW = {
804 {PC_OPCODE, NULL, NULL, 0, NULL,
817 0,0, // dest, bit instruction
824 pCodeInstruction pciRETURN = {
825 {PC_OPCODE, NULL, NULL, 0, NULL,
838 0,0, // dest, bit instruction
845 pCodeInstruction pciRLF = {
846 {PC_OPCODE, NULL, NULL, 0, NULL,
859 1,0, // dest, bit instruction
862 (PCC_C | PCC_REGISTER), // inCond
863 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
866 pCodeInstruction pciRLFW = {
867 {PC_OPCODE, NULL, NULL, 0, NULL,
880 0,0, // dest, bit instruction
883 (PCC_C | PCC_REGISTER), // inCond
884 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
887 pCodeInstruction pciRRF = {
888 {PC_OPCODE, NULL, NULL, 0, NULL,
901 1,0, // dest, bit instruction
904 (PCC_C | PCC_REGISTER), // inCond
905 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
908 pCodeInstruction pciRRFW = {
909 {PC_OPCODE, NULL, NULL, 0, NULL,
922 0,0, // dest, bit instruction
925 (PCC_C | PCC_REGISTER), // inCond
926 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
929 pCodeInstruction pciSUBWF = {
930 {PC_OPCODE, NULL, NULL, 0, NULL,
943 1,0, // dest, bit instruction
946 (PCC_W | PCC_REGISTER), // inCond
947 (PCC_REGISTER | PCC_Z) // outCond
950 pCodeInstruction pciSUBFW = {
951 {PC_OPCODE, NULL, NULL, 0, NULL,
964 0,0, // dest, bit instruction
967 (PCC_W | PCC_REGISTER), // inCond
968 (PCC_W | PCC_Z) // outCond
971 pCodeInstruction pciSUBLW = {
972 {PC_OPCODE, NULL, NULL, 0, NULL,
985 0,0, // dest, bit instruction
989 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
992 pCodeInstruction pciSWAPF = {
993 {PC_OPCODE, NULL, NULL, 0, NULL,
1006 1,0, // dest, bit instruction
1007 0,0, // branch, skip
1009 (PCC_REGISTER), // inCond
1010 (PCC_REGISTER) // outCond
1013 pCodeInstruction pciSWAPFW = {
1014 {PC_OPCODE, NULL, NULL, 0, NULL,
1020 NULL, // from branch
1027 0,0, // dest, bit instruction
1028 0,0, // branch, skip
1030 (PCC_REGISTER), // inCond
1034 pCodeInstruction pciTRIS = {
1035 {PC_OPCODE, NULL, NULL, 0, NULL,
1041 NULL, // from branch
1048 0,0, // dest, bit instruction
1049 0,0, // branch, skip
1052 PCC_REGISTER // outCond
1055 pCodeInstruction pciXORWF = {
1056 {PC_OPCODE, NULL, NULL, 0, NULL,
1062 NULL, // from branch
1069 1,0, // dest, bit instruction
1070 0,0, // branch, skip
1072 (PCC_W | PCC_REGISTER), // inCond
1073 (PCC_REGISTER | PCC_Z) // outCond
1076 pCodeInstruction pciXORFW = {
1077 {PC_OPCODE, NULL, NULL, 0, NULL,
1083 NULL, // from branch
1090 0,0, // dest, bit instruction
1091 0,0, // branch, skip
1093 (PCC_W | PCC_REGISTER), // inCond
1094 (PCC_W | PCC_Z) // outCond
1097 pCodeInstruction pciXORLW = {
1098 {PC_OPCODE, NULL, NULL, 0, NULL,
1104 NULL, // from branch
1111 0,0, // dest, bit instruction
1112 0,0, // branch, skip
1115 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1119 #define MAX_PIC14MNEMONICS 100
1120 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1122 /* This definition needs to be part of configure.in */
1123 // #define USE_VSNPRINTF
1125 #ifdef USE_VSNPRINTF
1126 // Alas, vsnprintf is not ANSI standard, and does not exist
1127 // on Solaris (and probably other non-Gnu flavored Unixes).
1129 /*-----------------------------------------------------------------*/
1130 /* SAFE_snprintf - like snprintf except the string pointer is */
1131 /* after the string has been printed to. This is */
1132 /* useful for printing to string as though if it */
1133 /* were a stream. */
1134 /*-----------------------------------------------------------------*/
1135 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1143 va_start(val, format);
1145 vsnprintf(*str, *size, format, val);
1151 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1159 #else // USE_VSNPRINTF
1161 // This version is *not* safe, despite the name.
1163 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1167 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1172 va_start(val, format);
1174 vsprintf(buffer, format, val);
1177 len = strlen(buffer);
1179 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1182 strcpy(*str, buffer);
1188 #endif // USE_VSNPRINTF
1191 extern void initStack(int base_address, int size);
1192 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1193 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1194 extern void init_pic(char *);
1196 void pCodeInitRegisters(void)
1199 initStack(0xfff, 8);
1200 init_pic(port->processor);
1202 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1203 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1204 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1205 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1206 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1207 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1209 pc_status.rIdx = IDX_STATUS;
1210 pc_fsr.rIdx = IDX_FSR;
1211 pc_indf.rIdx = IDX_INDF;
1212 pc_intcon.rIdx = IDX_INTCON;
1213 pc_pcl.rIdx = IDX_PCL;
1214 pc_pclath.rIdx = IDX_PCLATH;
1216 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1217 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1218 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1220 pc_kzero.rIdx = IDX_KZ;
1221 pc_wsave.rIdx = IDX_WSAVE;
1222 pc_ssave.rIdx = IDX_SSAVE;
1226 /*-----------------------------------------------------------------*/
1227 /* mnem2key - convert a pic mnemonic into a hash key */
1228 /* (BTW - this spreads the mnemonics quite well) */
1230 /*-----------------------------------------------------------------*/
1232 int mnem2key(char const *mnem)
1241 key += toupper(*mnem++) +1;
1245 return (key & 0x1f);
1249 void pic14initMnemonics(void)
1254 pCodeInstruction *pci;
1256 if(mnemonics_initialized)
1259 //FIXME - probably should NULL out the array before making the assignments
1260 //since we check the array contents below this initialization.
1262 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1263 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1264 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1265 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1266 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1267 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1268 pic14Mnemonics[POC_BCF] = &pciBCF;
1269 pic14Mnemonics[POC_BSF] = &pciBSF;
1270 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1271 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1272 pic14Mnemonics[POC_CALL] = &pciCALL;
1273 pic14Mnemonics[POC_COMF] = &pciCOMF;
1274 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1275 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1276 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1277 pic14Mnemonics[POC_DECF] = &pciDECF;
1278 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1279 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1280 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1281 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1282 pic14Mnemonics[POC_INCF] = &pciINCF;
1283 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1284 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1285 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1286 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1287 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1288 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1289 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1290 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1291 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1292 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1293 pic14Mnemonics[POC_NOP] = &pciNOP;
1294 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1295 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1296 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1297 pic14Mnemonics[POC_RLF] = &pciRLF;
1298 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1299 pic14Mnemonics[POC_RRF] = &pciRRF;
1300 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1301 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1302 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1303 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1304 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1305 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1306 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1307 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1308 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1309 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1311 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1312 if(pic14Mnemonics[i])
1313 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1314 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1317 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1318 pci = hTabNextItem(pic14MnemonicsHash, &key);
1321 mnemonics_initialized = 1;
1324 int getpCodePeepCommand(char *cmd);
1326 int getpCode(char *mnem,unsigned dest)
1329 pCodeInstruction *pci;
1330 int key = mnem2key(mnem);
1332 if(!mnemonics_initialized)
1333 pic14initMnemonics();
1335 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1339 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1340 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1344 pci = hTabNextItemWK (pic14MnemonicsHash);
1351 /*-----------------------------------------------------------------*
1352 * pic14initpCodePeepCommands
1354 *-----------------------------------------------------------------*/
1355 void pic14initpCodePeepCommands(void)
1363 hTabAddItem(&pic14pCodePeepCommandsHash,
1364 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1366 } while (peepCommands[i].cmd);
1368 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1371 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1372 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1377 /*-----------------------------------------------------------------
1380 *-----------------------------------------------------------------*/
1382 int getpCodePeepCommand(char *cmd)
1386 int key = mnem2key(cmd);
1389 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1392 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1393 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1397 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1404 char getpBlock_dbName(pBlock *pb)
1410 return pb->cmemmap->dbName;
1414 void pBlockConvert2ISR(pBlock *pb)
1425 /*-----------------------------------------------------------------*/
1426 /* movepBlock2Head - given the dbname of a pBlock, move all */
1427 /* instances to the front of the doubly linked */
1428 /* list of pBlocks */
1429 /*-----------------------------------------------------------------*/
1431 void movepBlock2Head(char dbName)
1435 pb = the_pFile->pbHead;
1439 if(getpBlock_dbName(pb) == dbName) {
1440 pBlock *pbn = pb->next;
1441 pb->next = the_pFile->pbHead;
1442 the_pFile->pbHead->prev = pb;
1443 the_pFile->pbHead = pb;
1446 pb->prev->next = pbn;
1448 // If the pBlock that we just moved was the last
1449 // one in the link of all of the pBlocks, then we
1450 // need to point the tail to the block just before
1451 // the one we moved.
1452 // Note: if pb->next is NULL, then pb must have
1453 // been the last pBlock in the chain.
1456 pbn->prev = pb->prev;
1458 the_pFile->pbTail = pb->prev;
1469 void copypCode(FILE *of, char dbName)
1473 if(!of || !the_pFile)
1476 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1477 if(getpBlock_dbName(pb) == dbName) {
1484 void pcode_test(void)
1487 DFPRINTF((stderr,"pcode is alive!\n"));
1497 /* create the file name */
1498 strcpy(buffer,srcFileName);
1499 strcat(buffer,".p");
1501 if( !(pFile = fopen(buffer, "w" ))) {
1502 werror(E_FILE_OPEN_ERR,buffer);
1506 fprintf(pFile,"pcode dump\n\n");
1508 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1509 fprintf(pFile,"\n\tNew pBlock\n\n");
1511 fprintf(pFile,"%s",pb->cmemmap->sname);
1513 fprintf(pFile,"internal pblock");
1515 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1516 printpBlock(pFile,pb);
1520 /*-----------------------------------------------------------------*/
1521 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1522 /* ister, RegCond will return the bit being referenced. */
1524 /* fixme - why not just OR in the pcop bit field */
1525 /*-----------------------------------------------------------------*/
1527 static int RegCond(pCodeOp *pcop)
1533 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1534 switch(PCORB(pcop)->bit) {
1548 /*-----------------------------------------------------------------*/
1549 /* newpCode - create and return a newly initialized pCode */
1551 /* fixme - rename this */
1553 /* The purpose of this routine is to create a new Instruction */
1554 /* pCode. This is called by gen.c while the assembly code is being */
1558 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1559 /* (note that the op is analogous to but not the */
1560 /* same thing as the opcode of the instruction.) */
1561 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1564 /* a pointer to the new malloc'd pCode is returned. */
1568 /*-----------------------------------------------------------------*/
1569 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1571 pCodeInstruction *pci ;
1573 if(!mnemonics_initialized)
1574 pic14initMnemonics();
1576 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1578 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1579 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1582 if(pci->inCond == PCC_EXAMINE_PCOP)
1583 pci->inCond = RegCond(pcop);
1585 if(pci->outCond == PCC_EXAMINE_PCOP)
1586 pci->outCond = RegCond(pcop);
1588 pci->pc.prev = pci->pc.next = NULL;
1589 return (pCode *)pci;
1592 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1598 /*-----------------------------------------------------------------*/
1599 /* newpCodeWild - create a "wild" as in wild card pCode */
1601 /* Wild pcodes are used during the peep hole optimizer to serve */
1602 /* as place holders for any instruction. When a snippet of code is */
1603 /* compared to a peep hole rule, the wild card opcode will match */
1604 /* any instruction. However, the optional operand and label are */
1605 /* additional qualifiers that must also be matched before the */
1606 /* line (of assembly code) is declared matched. Note that the */
1607 /* operand may be wild too. */
1609 /* Note, a wild instruction is specified just like a wild var: */
1610 /* %4 ; A wild instruction, */
1611 /* See the peeph.def file for additional examples */
1613 /*-----------------------------------------------------------------*/
1615 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1620 pcw = Safe_calloc(1,sizeof(pCodeWild));
1622 pcw->pci.pc.type = PC_WILD;
1623 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1624 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1625 pcw->pci.pc.pb = NULL;
1627 // pcw->pci.pc.analyze = genericAnalyze;
1628 pcw->pci.pc.destruct = genericDestruct;
1629 pcw->pci.pc.print = genericPrint;
1631 pcw->id = pCodeID; // this is the 'n' in %n
1632 pcw->operand = optional_operand;
1633 pcw->label = optional_label;
1635 pcw->mustBeBitSkipInst = 0;
1636 pcw->mustNotBeBitSkipInst = 0;
1637 pcw->invertBitSkipInst = 0;
1639 return ( (pCode *)pcw);
1643 /*-----------------------------------------------------------------*/
1644 /* newPcodeInlineP - create a new pCode from a char string */
1645 /*-----------------------------------------------------------------*/
1648 pCode *newpCodeInlineP(char *cP)
1653 pcc = Safe_calloc(1,sizeof(pCodeComment));
1655 pcc->pc.type = PC_INLINE;
1656 pcc->pc.prev = pcc->pc.next = NULL;
1657 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1660 // pcc->pc.analyze = genericAnalyze;
1661 pcc->pc.destruct = genericDestruct;
1662 pcc->pc.print = genericPrint;
1665 pcc->comment = Safe_strdup(cP);
1667 pcc->comment = NULL;
1669 return ( (pCode *)pcc);
1673 /*-----------------------------------------------------------------*/
1674 /* newPcodeCharP - create a new pCode from a char string */
1675 /*-----------------------------------------------------------------*/
1677 pCode *newpCodeCharP(char *cP)
1682 pcc = Safe_calloc(1,sizeof(pCodeComment));
1684 pcc->pc.type = PC_COMMENT;
1685 pcc->pc.prev = pcc->pc.next = NULL;
1686 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1689 // pcc->pc.analyze = genericAnalyze;
1690 pcc->pc.destruct = genericDestruct;
1691 pcc->pc.print = genericPrint;
1694 pcc->comment = Safe_strdup(cP);
1696 pcc->comment = NULL;
1698 return ( (pCode *)pcc);
1702 /*-----------------------------------------------------------------*/
1703 /* newpCodeFunction - */
1704 /*-----------------------------------------------------------------*/
1707 pCode *newpCodeFunction(char *mod,char *f)
1711 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1712 //_ALLOC(pcf,sizeof(pCodeFunction));
1714 pcf->pc.type = PC_FUNCTION;
1715 pcf->pc.prev = pcf->pc.next = NULL;
1716 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1719 // pcf->pc.analyze = genericAnalyze;
1720 pcf->pc.destruct = genericDestruct;
1721 pcf->pc.print = pCodePrintFunction;
1726 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1727 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1728 strcpy(pcf->modname,mod);
1730 pcf->modname = NULL;
1733 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1734 pcf->fname = Safe_calloc(1,strlen(f)+1);
1735 strcpy(pcf->fname,f);
1739 return ( (pCode *)pcf);
1743 /*-----------------------------------------------------------------*/
1745 /*-----------------------------------------------------------------*/
1748 pCode *newpCodeFlow(void )
1752 //_ALLOC(pcflow,sizeof(pCodeFlow));
1753 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1755 pcflow->pc.type = PC_FLOW;
1756 pcflow->pc.prev = pcflow->pc.next = NULL;
1757 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1758 pcflow->pc.pb = NULL;
1760 // pcflow->pc.analyze = genericAnalyze;
1761 pcflow->pc.destruct = genericDestruct;
1762 pcflow->pc.print = genericPrint;
1764 pcflow->pc.seq = GpcFlowSeq++;
1767 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1769 pcflow->from = pcflow->to = NULL;
1771 pcflow->inCond = PCC_NONE;
1772 pcflow->outCond = PCC_NONE;
1775 return ( (pCode *)pcflow);
1779 /*-----------------------------------------------------------------*/
1780 /* newpCodeCSource - create a new pCode Source Symbol */
1781 /*-----------------------------------------------------------------*/
1783 pCode *newpCodeCSource(int ln, char *f, char *l)
1788 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1790 pccs->pc.type = PC_CSOURCE;
1791 pccs->pc.prev = pccs->pc.next = NULL;
1794 pccs->pc.destruct = genericDestruct;
1795 pccs->pc.print = genericPrint;
1797 pccs->line_number = ln;
1799 pccs->line = Safe_strdup(l);
1804 pccs->file_name = Safe_strdup(f);
1806 pccs->file_name = NULL;
1808 return ( (pCode *)pccs);
1811 /*-----------------------------------------------------------------*/
1812 /* pCodeLabelDestruct - free memory used by a label. */
1813 /*-----------------------------------------------------------------*/
1814 static void pCodeLabelDestruct(pCode *pc)
1820 if((pc->type == PC_LABEL) && PCL(pc)->label)
1821 free(PCL(pc)->label);
1827 pCode *newpCodeLabel(char *name, int key)
1833 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1835 pcl->pc.type = PC_LABEL;
1836 pcl->pc.prev = pcl->pc.next = NULL;
1837 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1840 // pcl->pc.analyze = genericAnalyze;
1841 pcl->pc.destruct = pCodeLabelDestruct;
1842 pcl->pc.print = pCodePrintLabel;
1848 sprintf(s,"_%05d_DS_",key);
1853 pcl->label = Safe_strdup(s);
1856 return ( (pCode *)pcl);
1861 /*-----------------------------------------------------------------*/
1862 /* newpBlock - create and return a pointer to a new pBlock */
1863 /*-----------------------------------------------------------------*/
1864 pBlock *newpBlock(void)
1869 PpB = Safe_calloc(1,sizeof(pBlock) );
1870 PpB->next = PpB->prev = NULL;
1872 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1873 PpB->tregisters = NULL;
1880 /*-----------------------------------------------------------------*/
1881 /* newpCodeChain - create a new chain of pCodes */
1882 /*-----------------------------------------------------------------*
1884 * This function will create a new pBlock and the pointer to the
1885 * pCode that is passed in will be the first pCode in the block.
1886 *-----------------------------------------------------------------*/
1889 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1892 pBlock *pB = newpBlock();
1894 pB->pcHead = pB->pcTail = pc;
1901 /*-----------------------------------------------------------------*/
1902 /* newpCodeOpLabel - Create a new label given the key */
1903 /* Note, a negative key means that the label is part of wild card */
1904 /* (and hence a wild card label) used in the pCodePeep */
1905 /* optimizations). */
1906 /*-----------------------------------------------------------------*/
1908 pCodeOp *newpCodeOpLabel(char *name, int key)
1911 static int label_key=-1;
1915 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1916 pcop->type = PO_LABEL;
1921 sprintf(s=buffer,"_%05d_DS_",key);
1923 s = name, key = label_key--;
1926 pcop->name = Safe_strdup(s);
1928 ((pCodeOpLabel *)pcop)->key = key;
1933 /*-----------------------------------------------------------------*/
1934 /*-----------------------------------------------------------------*/
1935 pCodeOp *newpCodeOpLit(int lit)
1941 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1942 pcop->type = PO_LITERAL;
1946 sprintf(s,"0x%02x",lit);
1948 pcop->name = Safe_strdup(s);
1951 ((pCodeOpLit *)pcop)->lit = lit;
1956 /*-----------------------------------------------------------------*/
1957 /*-----------------------------------------------------------------*/
1958 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
1962 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1963 pcop->type = PO_IMMEDIATE;
1965 pcop->name = Safe_strdup(name);
1966 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
1972 PCOI(pcop)->index = index;
1973 PCOI(pcop)->offset = offset;
1974 PCOI(pcop)->_const = code_space;
1979 /*-----------------------------------------------------------------*/
1980 /*-----------------------------------------------------------------*/
1981 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
1987 if(!pcwb || !subtype) {
1988 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1992 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1993 pcop->type = PO_WILD;
1994 sprintf(s,"%%%d",id);
1995 pcop->name = Safe_strdup(s);
1997 PCOW(pcop)->id = id;
1998 PCOW(pcop)->pcwb = pcwb;
1999 PCOW(pcop)->subtype = subtype;
2000 PCOW(pcop)->matched = NULL;
2005 /*-----------------------------------------------------------------*/
2006 /*-----------------------------------------------------------------*/
2007 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2011 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2012 pcop->type = PO_GPR_BIT;
2014 pcop->name = Safe_strdup(s);
2018 PCORB(pcop)->bit = bit;
2019 PCORB(pcop)->inBitSpace = inBitSpace;
2024 /*-----------------------------------------------------------------*
2025 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2027 * If rIdx >=0 then a specific register from the set of registers
2028 * will be selected. If rIdx <0, then a new register will be searched
2030 *-----------------------------------------------------------------*/
2032 pCodeOp *newpCodeOpReg(int rIdx)
2036 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2041 PCOR(pcop)->rIdx = rIdx;
2042 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2044 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2047 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2048 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2051 pcop->type = PCOR(pcop)->r->pc_type;
2056 pCodeOp *newpCodeOpRegFromStr(char *name)
2060 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2061 PCOR(pcop)->r = allocRegByName(name, 1);
2062 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2063 pcop->type = PCOR(pcop)->r->pc_type;
2064 pcop->name = PCOR(pcop)->r->name;
2069 /*-----------------------------------------------------------------*/
2070 /*-----------------------------------------------------------------*/
2072 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2079 pcop = newpCodeOpBit(name, -1,0);
2083 pcop = newpCodeOpLit(-1);
2087 pcop = newpCodeOpLabel(NULL,-1);
2090 pcop = newpCodeOpReg(-1);
2094 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2097 pcop->name = Safe_strdup(name);
2105 /*-----------------------------------------------------------------*/
2106 /*-----------------------------------------------------------------*/
2107 void pCodeConstString(char *name, char *value)
2111 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2116 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2120 sprintf(buffer,"; %s = %s",name,value);
2122 addpCode2pBlock(pb,newpCodeCharP(buffer));
2123 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2126 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2132 /*-----------------------------------------------------------------*/
2133 /*-----------------------------------------------------------------*/
2134 void pCodeReadCodeTable(void)
2138 fprintf(stderr, " %s\n",__FUNCTION__);
2140 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2144 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2145 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2146 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2147 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2149 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2150 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2151 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2152 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2157 /*-----------------------------------------------------------------*/
2158 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2159 /*-----------------------------------------------------------------*/
2160 void addpCode2pBlock(pBlock *pb, pCode *pc)
2163 /* If this is the first pcode to be added to a block that
2164 * was initialized with a NULL pcode, then go ahead and
2165 * make this pcode the head and tail */
2166 pb->pcHead = pb->pcTail = pc;
2168 pb->pcTail->next = pc;
2169 pc->prev = pb->pcTail;
2176 /*-----------------------------------------------------------------*/
2177 /* addpBlock - place a pBlock into the pFile */
2178 /*-----------------------------------------------------------------*/
2179 void addpBlock(pBlock *pb)
2181 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2184 /* First time called, we'll pass through here. */
2185 //_ALLOC(the_pFile,sizeof(pFile));
2186 the_pFile = Safe_calloc(1,sizeof(pFile));
2187 the_pFile->pbHead = the_pFile->pbTail = pb;
2188 the_pFile->functions = NULL;
2192 the_pFile->pbTail->next = pb;
2193 pb->prev = the_pFile->pbTail;
2195 the_pFile->pbTail = pb;
2198 /*-----------------------------------------------------------------*/
2199 /* removepBlock - remove a pBlock from the pFile */
2200 /*-----------------------------------------------------------------*/
2201 void removepBlock(pBlock *pb)
2209 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2211 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2214 if(pbs == the_pFile->pbHead)
2215 the_pFile->pbHead = pbs->next;
2217 if (pbs == the_pFile->pbTail)
2218 the_pFile->pbTail = pbs->prev;
2221 pbs->next->prev = pbs->prev;
2224 pbs->prev->next = pbs->next;
2231 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2235 /*-----------------------------------------------------------------*/
2236 /* printpCode - write the contents of a pCode to a file */
2237 /*-----------------------------------------------------------------*/
2238 void printpCode(FILE *of, pCode *pc)
2249 fprintf(of,"warning - unable to print pCode\n");
2252 /*-----------------------------------------------------------------*/
2253 /* printpBlock - write the contents of a pBlock to a file */
2254 /*-----------------------------------------------------------------*/
2255 void printpBlock(FILE *of, pBlock *pb)
2265 for(pc = pb->pcHead; pc; pc = pc->next)
2270 /*-----------------------------------------------------------------*/
2272 /* pCode processing */
2276 /*-----------------------------------------------------------------*/
2278 static void unlinkPC(pCode *pc)
2284 fprintf(stderr,"Unlinking: ");
2285 printpCode(stderr, pc);
2288 pc->prev->next = pc->next;
2290 pc->next->prev = pc->prev;
2292 pc->prev = pc->next = NULL;
2295 static void genericDestruct(pCode *pc)
2297 fprintf(stderr,"warning, calling default pCode destructor\n");
2306 /*-----------------------------------------------------------------*/
2307 /*-----------------------------------------------------------------*/
2308 void pBlockRegs(FILE *of, pBlock *pb)
2313 r = setFirstItem(pb->tregisters);
2315 r = setNextItem(pb->tregisters);
2320 /*-----------------------------------------------------------------*/
2321 /*-----------------------------------------------------------------*/
2322 char *get_op(pCodeOp *pcop)
2325 static char buffer[50];
2331 switch(pcop->type) {
2334 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2335 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2337 return PCOR(pcop)->r->name;
2340 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2341 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2345 // return PCOR(pcc->pcop)->r)->name;
2348 size = sizeof(buffer);
2349 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2350 if(PCOI(pcop)->_const) {
2352 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2353 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2356 8 * PCOI(pcop)->offset );
2358 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2361 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2362 SAFE_snprintf(&s,&size,"(%s + %d)",
2364 PCOI(pcop)->index );
2366 SAFE_snprintf(&s,&size,"%s",pcop->name);
2373 size = sizeof(buffer);
2374 if( PCOR(pcop)->instance) {
2375 SAFE_snprintf(&s,&size,"(%s + %d)",
2377 PCOR(pcop)->instance );
2378 //fprintf(stderr,"PO_DIR %s\n",buffer);
2380 SAFE_snprintf(&s,&size,"%s",pcop->name);
2390 return "NO operand";
2394 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2396 static char *get_op_from_instruction( pCodeInstruction *pcc)
2400 return get_op(pcc->pcop);
2402 return ("ERROR Null: "__FUNCTION__);
2406 /*-----------------------------------------------------------------*/
2407 /*-----------------------------------------------------------------*/
2408 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2411 fprintf(of,"pcodeopprint- not implemented\n");
2414 /*-----------------------------------------------------------------*/
2415 /*-----------------------------------------------------------------*/
2416 char *pCode2str(char *str, int size, pCode *pc)
2424 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2426 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2428 if(PCI(pc)->isBitInst) {
2429 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2430 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2431 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2432 PCI(pc)->pcop->name ,
2433 PCI(pc)->pcop->name );
2435 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2436 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2437 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2438 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2440 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2441 //PCI(pc)->pcop->t.bit );
2444 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2445 if( PCI(pc)->num_ops == 2)
2446 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2448 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2451 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2453 if( PCI(pc)->num_ops == 2)
2454 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2462 /* assuming that comment ends with a \n */
2463 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2467 /* assuming that inline code ends with a \n */
2468 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2472 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2475 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2478 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2481 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2484 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2493 /*-----------------------------------------------------------------*/
2494 /* genericPrint - the contents of a pCode to a file */
2495 /*-----------------------------------------------------------------*/
2496 static void genericPrint(FILE *of, pCode *pc)
2504 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2508 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2512 // If the opcode has a label, print that first
2514 pBranch *pbl = PCI(pc)->label;
2515 while(pbl && pbl->pc) {
2516 if(pbl->pc->type == PC_LABEL)
2517 pCodePrintLabel(of, pbl->pc);
2523 genericPrint(of,PCODE(PCI(pc)->cline));
2528 pCode2str(str, 256, pc);
2530 fprintf(of,"%s",str);
2533 fprintf(of, "\t;key=%03x",pc->seq);
2535 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2539 pBranch *dpb = pc->to; // debug
2541 switch ( dpb->pc->type) {
2543 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2546 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2549 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2552 fprintf(of, "\t;flow");
2566 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2567 if(PCW(pc)->pci.label)
2568 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2570 if(PCW(pc)->operand) {
2571 fprintf(of,";\toperand ");
2572 pCodeOpPrint(of,PCW(pc)->operand );
2577 fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2581 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2585 fprintf(of,"unknown pCode type %d\n",pc->type);
2590 /*-----------------------------------------------------------------*/
2591 /* pCodePrintFunction - prints function begin/end */
2592 /*-----------------------------------------------------------------*/
2594 static void pCodePrintFunction(FILE *of, pCode *pc)
2600 if( ((pCodeFunction *)pc)->modname)
2601 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2603 if(PCF(pc)->fname) {
2604 pBranch *exits = PCF(pc)->to;
2606 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2609 exits = exits->next;
2612 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2615 if((PCF(pc)->from &&
2616 PCF(pc)->from->pc->type == PC_FUNCTION &&
2617 PCF(PCF(pc)->from->pc)->fname) )
2618 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2620 fprintf(of,"; exit point [can't find entry point]\n");
2623 /*-----------------------------------------------------------------*/
2624 /* pCodePrintLabel - prints label */
2625 /*-----------------------------------------------------------------*/
2627 static void pCodePrintLabel(FILE *of, pCode *pc)
2634 fprintf(of,"%s\n",PCL(pc)->label);
2635 else if (PCL(pc)->key >=0)
2636 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2638 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2641 /*-----------------------------------------------------------------*/
2642 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2643 /* remove it if it is found. */
2644 /*-----------------------------------------------------------------*/
2645 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2652 if(pcl->type == PC_OPCODE)
2653 b = PCI(pcl)->label;
2655 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2665 bprev->next = b->next; /* Not first pCode in chain */
2669 PCI(pcl)->label = b->next; /* First pCode in chain */
2672 return; /* A label can't occur more than once */
2689 bprev->next = b->next; /* Not first pCode in chain */
2693 pcl->label = b->next; /* First pCode in chain */
2696 return; /* A label can't occur more than once */
2704 /*-----------------------------------------------------------------*/
2705 /*-----------------------------------------------------------------*/
2706 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2722 /*-----------------------------------------------------------------*/
2723 /* pBranchLink - given two pcodes, this function will link them */
2724 /* together through their pBranches */
2725 /*-----------------------------------------------------------------*/
2726 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2730 // Declare a new branch object for the 'from' pCode.
2732 //_ALLOC(b,sizeof(pBranch));
2733 b = Safe_calloc(1,sizeof(pBranch));
2734 b->pc = PCODE(t); // The link to the 'to' pCode.
2737 f->to = pBranchAppend(f->to,b);
2739 // Now do the same for the 'to' pCode.
2741 //_ALLOC(b,sizeof(pBranch));
2742 b = Safe_calloc(1,sizeof(pBranch));
2746 t->from = pBranchAppend(t->from,b);
2751 /*-----------------------------------------------------------------*/
2752 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2754 /*-----------------------------------------------------------------*/
2755 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2768 /*-----------------------------------------------------------------*/
2769 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2770 /*-----------------------------------------------------------------*/
2771 static void pCodeUnlink(pCode *pc)
2776 if(!pc->prev || !pc->next) {
2777 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2781 /* first remove the pCode from the chain */
2782 pc->prev->next = pc->next;
2783 pc->next->prev = pc->prev;
2785 /* Now for the hard part... */
2787 /* Remove the branches */
2791 pc1 = pb1->pc; /* Get the pCode that branches to the
2792 * one we're unlinking */
2794 /* search for the link back to this pCode (the one we're
2796 if(pb2 = pBranchFind(pc1->to,pc)) {
2797 pb2->pc = pc->to->pc; // make the replacement
2799 /* if the pCode we're unlinking contains multiple 'to'
2800 * branches (e.g. this a skip instruction) then we need
2801 * to copy these extra branches to the chain. */
2803 pBranchAppend(pb2, pc->to->next);
2812 /*-----------------------------------------------------------------*/
2813 /*-----------------------------------------------------------------*/
2815 static void genericAnalyze(pCode *pc)
2825 // Go through the pCodes that are in pCode chain and link
2826 // them together through the pBranches. Note, the pCodes
2827 // are linked together as a contiguous stream like the
2828 // assembly source code lines. The linking here mimics this
2829 // except that comments are not linked in.
2831 pCode *npc = pc->next;
2833 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2834 pBranchLink(pc,npc);
2839 /* reached the end of the pcode chain without finding
2840 * an instruction we could link to. */
2844 fprintf(stderr,"analyze PC_FLOW\n");
2851 /*-----------------------------------------------------------------*/
2852 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2856 if(pc->type == PC_LABEL) {
2857 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2860 if(pc->type == PC_OPCODE) {
2861 pbr = PCI(pc)->label;
2863 if(pbr->pc->type == PC_LABEL) {
2864 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2874 /*-----------------------------------------------------------------*/
2875 /* findLabel - Search the pCode for a particular label */
2876 /*-----------------------------------------------------------------*/
2877 pCode * findLabel(pCodeOpLabel *pcop_label)
2885 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2886 for(pc = pb->pcHead; pc; pc = pc->next)
2887 if(compareLabel(pc,pcop_label))
2892 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2896 /*-----------------------------------------------------------------*/
2897 /* findNextpCode - given a pCode, find the next of type 'pct' */
2898 /* in the linked list */
2899 /*-----------------------------------------------------------------*/
2900 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2913 /*-----------------------------------------------------------------*/
2914 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2915 /* in the linked list */
2916 /*-----------------------------------------------------------------*/
2917 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2929 /*-----------------------------------------------------------------*/
2930 /* findNextInstruction - given a pCode, find the next instruction */
2931 /* in the linked list */
2932 /*-----------------------------------------------------------------*/
2933 pCode * findNextInstruction(pCode *pci)
2938 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2942 fprintf(stderr,"findNextInstruction: ");
2943 printpCode(stderr, pc);
2948 //fprintf(stderr,"Couldn't find instruction\n");
2952 /*-----------------------------------------------------------------*/
2953 /* findNextInstruction - given a pCode, find the next instruction */
2954 /* in the linked list */
2955 /*-----------------------------------------------------------------*/
2956 pCode * findPrevInstruction(pCode *pci)
2958 return findPrevpCode(pci, PC_OPCODE);
2961 /*-----------------------------------------------------------------*/
2962 /* findFunctionEnd - given a pCode find the end of the function */
2963 /* that contains it */
2964 /*-----------------------------------------------------------------*/
2965 pCode * findFunctionEnd(pCode *pc)
2969 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2975 fprintf(stderr,"Couldn't find function end\n");
2980 /*-----------------------------------------------------------------*/
2981 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2982 /* instruction with which it is associated. */
2983 /*-----------------------------------------------------------------*/
2984 static void AnalyzeLabel(pCode *pc)
2993 static void AnalyzeGOTO(pCode *pc)
2996 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3000 static void AnalyzeSKIP(pCode *pc)
3003 pBranchLink(pc,findNextInstruction(pc->next));
3004 pBranchLink(pc,findNextInstruction(pc->next->next));
3008 static void AnalyzeRETURN(pCode *pc)
3011 // branch_link(pc,findFunctionEnd(pc->next));
3017 /*-----------------------------------------------------------------*/
3018 /*-----------------------------------------------------------------*/
3019 regs * getRegFromInstruction(pCode *pc)
3024 PCI(pc)->num_ops == 0 )
3027 switch(PCI(pc)->pcop->type) {
3030 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3034 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3035 return PCOR(PCI(pc)->pcop)->r;
3038 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3039 return NULL; // PCOR(PCI(pc)->pcop)->r;
3042 return PCOR(PCI(pc)->pcop)->r;
3045 //fprintf(stderr, "getRegFromInstruction - dir\n");
3046 return PCOR(PCI(pc)->pcop)->r;
3048 //fprintf(stderr, "getRegFromInstruction - literal\n");
3052 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3053 //genericPrint(stderr, pc);
3061 /*-----------------------------------------------------------------*/
3062 /*-----------------------------------------------------------------*/
3064 void AnalyzepBlock(pBlock *pb)
3071 /* Find all of the registers used in this pBlock
3072 * by looking at each instruction and examining it's
3075 for(pc = pb->pcHead; pc; pc = pc->next) {
3077 /* Is this an instruction with operands? */
3078 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3080 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3082 /* Loop through all of the registers declared so far in
3083 this block and see if we find this one there */
3085 regs *r = setFirstItem(pb->tregisters);
3088 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3089 PCOR(PCI(pc)->pcop)->r = r;
3092 r = setNextItem(pb->tregisters);
3096 /* register wasn't found */
3097 r = Safe_calloc(1, sizeof(regs));
3098 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3099 addSet(&pb->tregisters, r);
3100 PCOR(PCI(pc)->pcop)->r = r;
3101 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3103 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3106 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3107 if(PCOR(PCI(pc)->pcop)->r) {
3108 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3109 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3111 if(PCI(pc)->pcop->name)
3112 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3114 fprintf(stderr,"ERROR: NULL register\n");
3123 /*-----------------------------------------------------------------*/
3125 /*-----------------------------------------------------------------*/
3126 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3128 void InsertpFlow(pCode *pc, pCode **pflow)
3130 PCFL(*pflow)->end = pc;
3132 if(!pc || !pc->next)
3135 *pflow = newpCodeFlow();
3136 pCodeInsertAfter(pc, *pflow);
3139 /*-----------------------------------------------------------------*/
3140 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3141 /* the flow blocks. */
3143 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3144 * point the instruction flow changes.
3146 /*-----------------------------------------------------------------*/
3147 void BuildFlow(pBlock *pb)
3150 pCode *last_pci=NULL;
3157 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3158 /* Insert a pCodeFlow object at the beginning of a pBlock */
3160 pflow = newpCodeFlow(); /* Create a new Flow object */
3161 pflow->next = pb->pcHead; /* Make the current head the next object */
3162 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3163 pb->pcHead = pflow; /* Make the Flow object the head */
3166 for( pc = findNextInstruction(pb->pcHead);
3167 (pc=findNextInstruction(pc)) != NULL; ) {
3170 PCI(pc)->pcflow = PCFL(pflow);
3172 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
3174 /* The instruction immediately following this one
3175 * marks the beginning of a new flow segment */
3177 InsertpFlow(pc, &pflow);
3180 } else if (PCI_HAS_LABEL(pc)) {
3182 /* This instruction marks the beginning of a
3183 * new flow segment */
3187 InsertpFlow(pc->prev, &pflow);
3189 PCI(pc)->pcflow = PCFL(pflow);
3196 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3197 PCFL(pflow)->end = pb->pcTail;
3200 /*-----------------------------------------------------------------*/
3201 /*-----------------------------------------------------------------*/
3202 void dumpCond(int cond)
3205 static char *pcc_str[] = {
3219 int ncond = sizeof(pcc_str) / sizeof(char *);
3222 fprintf(stderr, "0x%04X\n",cond);
3224 for(i=0,j=1; i<ncond; i++, j<<=1)
3226 fprintf(stderr, " %s\n",pcc_str[i]);
3230 /*-----------------------------------------------------------------*/
3231 /*-----------------------------------------------------------------*/
3232 void FillFlow(pCodeFlow *pcflow)
3241 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3243 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3245 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3254 int inCond = PCI(pc)->inCond;
3255 int outCond = PCI(pc)->outCond;
3257 if( (reg = getRegFromInstruction(pc)) != NULL) {
3258 if(isSTATUS_REG(reg)) {
3260 //fprintf(stderr, " FillFlow - Status register\n");
3262 /* Check to see if the register banks are changing */
3263 if(PCI(pc)->isModReg) {
3265 pCodeOp *pcop = PCI(pc)->pcop;
3266 switch(PCI(pc)->op) {
3268 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3269 fprintf(stderr, " FillFlow - Set RP0\n");
3270 //outCond |= PCC_REG_BANK1;
3271 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3272 fprintf(stderr, " FillFlow - Set RP1\n");
3273 //outCond |= PCC_REG_BANK3;
3277 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3278 fprintf(stderr, " FillFlow - Clr RP0\n");
3279 //outCond |= PCC_REG_BANK1;
3280 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3281 fprintf(stderr, " FillFlow - Clr RP1\n");
3282 //outCond |= PCC_REG_BANK3;
3286 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3287 genericPrint(stderr, pc);
3292 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3296 pcflow->inCond |= (inCond & ~pcflow->outCond);
3297 pcflow->outCond |= outCond;
3302 pc = findNextpCode(pc->next, PC_OPCODE);
3303 } while (pc && (pc != pcflow->end));
3307 fprintf(stderr, " FillFlow - Bad end of flow\n");
3310 fprintf(stderr, " FillFlow inCond: ");
3311 dumpCond(pcflow->inCond);
3312 fprintf(stderr, " FillFlow outCond: ");
3313 dumpCond(pcflow->outCond);
3316 /*-----------------------------------------------------------------*/
3317 /*-----------------------------------------------------------------*/
3318 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3321 if(!from || !to || !to->pcflow || !from->pcflow)
3324 addSet(&(from->pcflow->to), to->pcflow);
3325 addSet(&(to->pcflow->from), from->pcflow);
3329 /*-----------------------------------------------------------------*/
3330 /*-----------------------------------------------------------------*/
3331 void LinkFlow(pBlock *pb)
3338 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3339 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3340 pcflow = pcflow->next) {
3343 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3345 //FillFlow(PCFL(pcflow));
3347 pc = PCFL(pcflow)->end;
3349 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3350 if(isPCI_SKIP(pc)) {
3351 //fprintf(stderr, "ends with skip\n");
3352 pct=findNextInstruction(pc->next);
3353 LinkFlow_pCode(PCI(pc),PCI(pct));
3354 pct=findNextInstruction(pct->next);
3355 LinkFlow_pCode(PCI(pc),PCI(pct));
3359 if(isPCI_BRANCH(pc)) {
3360 //fprintf(stderr, "ends with branch\n");
3366 fprintf(stderr, "has an unrecognized ending:\n");
3367 pc->print(stderr,pc);
3370 fprintf(stderr, "has no end pcode\n");
3375 /*-----------------------------------------------------------------*/
3376 /*-----------------------------------------------------------------*/
3377 int OptimizepBlock(pBlock *pb)
3382 if(!pb || !peepOptimizing)
3385 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3387 for(pc = pb->pcHead; pc; pc = pc->next)
3388 matches += pCodePeepMatchRule(pc);
3391 pc = findNextInstruction(pb->pcHead);
3396 if(pCodePeepMatchRule(pc)) {
3401 pc = findNextInstruction(pcprev->next);
3403 pc = findNextInstruction(pb->pcHead);
3405 pc = findNextInstruction(pc->next);
3409 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3414 /*-----------------------------------------------------------------*/
3415 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3416 /*-----------------------------------------------------------------*/
3417 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3421 for(pc = pcs; pc; pc = pc->next) {
3423 if((pc->type == PC_OPCODE) &&
3425 (PCI(pc)->pcop->type == PO_LABEL) &&
3426 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3434 /*-----------------------------------------------------------------*/
3435 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3436 /* pCode chain if they're not used. */
3437 /*-----------------------------------------------------------------*/
3438 void pBlockRemoveUnusedLabels(pBlock *pb)
3440 pCode *pc; pCodeLabel *pcl;
3445 for(pc = pb->pcHead; pc; pc = pc->next) {
3447 if(pc->type == PC_LABEL)
3449 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3450 pcl = PCL(PCI(pc)->label->pc);
3453 /* This pCode is a label, so search the pBlock to see if anyone
3456 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3457 /* Couldn't find an instruction that refers to this label
3458 * So, unlink the pCode label from it's pCode chain
3459 * and destroy the label */
3461 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
3462 if(pc->type == PC_LABEL) {
3464 pCodeLabelDestruct(pc);
3466 unlinkpCodeFromBranch(pc, PCODE(pcl));
3467 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3478 /*-----------------------------------------------------------------*/
3479 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3480 /* chain and put them into pBranches that are */
3481 /* associated with the appropriate pCode */
3483 /*-----------------------------------------------------------------*/
3484 void pBlockMergeLabels(pBlock *pb)
3487 pCode *pc, *pcnext=NULL;
3492 /* First, Try to remove any unused labels */
3493 //pBlockRemoveUnusedLabels(pb);
3495 /* Now loop through the pBlock and merge the labels with the opcodes */
3497 for(pc = pb->pcHead; pc; pc = pc->next) {
3499 if(pc->type == PC_LABEL) {
3501 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
3502 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3503 if((pcnext = findNextInstruction(pc) )) {
3505 pCode *pcn = pc->next;
3507 // Unlink the pCode label from it's pCode chain
3510 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3511 // And link it into the instruction's pBranch labels. (Note, since
3512 // it's possible to have multiple labels associated with one instruction
3513 // we must provide a means to accomodate the additional labels. Thus
3514 // the labels are placed into the singly-linked list "label" as
3515 // opposed to being a single member of the pCodeInstruction.)
3517 //_ALLOC(pbr,sizeof(pBranch));
3518 pbr = Safe_calloc(1,sizeof(pBranch));
3523 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3528 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
3530 } else if(pc->type == PC_CSOURCE) {
3532 /* merge the source line symbolic info into the next instruction */
3533 if((pcnext = findNextInstruction(pc) )) {
3535 pCode *pcn = pc->next;
3537 // Unlink the pCode label from it's pCode chain
3539 PCI(pcnext)->cline = PCCS(pc);
3540 //fprintf(stderr, "merging CSRC\n");
3541 //genericPrint(stderr,pcnext);
3548 pBlockRemoveUnusedLabels(pb);
3552 /*-----------------------------------------------------------------*/
3553 /*-----------------------------------------------------------------*/
3554 int OptimizepCode(char dbName)
3556 #define MAX_PASSES 4
3565 DFPRINTF((stderr," Optimizing pCode\n"));
3569 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3570 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3571 matches += OptimizepBlock(pb);
3574 while(matches && ++passes < MAX_PASSES);
3579 /*-----------------------------------------------------------------*/
3580 /* popCopyGPR2Bit - copy a pcode operator */
3581 /*-----------------------------------------------------------------*/
3583 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3587 pcop = newpCodeOpBit(pc->name, bitval, 0);
3589 if( !( (pcop->type == PO_LABEL) ||
3590 (pcop->type == PO_LITERAL) ||
3591 (pcop->type == PO_STR) ))
3592 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3600 /*-----------------------------------------------------------------*/
3601 /*-----------------------------------------------------------------*/
3602 int InstructionRegBank(pCode *pc)
3606 if( (reg = getRegFromInstruction(pc)) == NULL)
3609 return REG_BANK(reg);
3614 /*-----------------------------------------------------------------*/
3615 /*-----------------------------------------------------------------*/
3616 void FixRegisterBanking(pBlock *pb)
3628 pc = findNextpCode(pb->pcHead, PC_FLOW);
3631 /* loop through all of the flow blocks with in one pblock */
3633 //fprintf(stderr,"Register banking\n");
3636 /* at this point, pc should point to a PC_FLOW object */
3639 /* for each flow block, determine the register banking
3644 //genericPrint(stderr, pc);
3646 reg = getRegFromInstruction(pc);
3649 fprintf(stderr, " %s ",reg->name);
3650 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3654 if(reg && REG_BANK(reg)!=cur_bank) {
3655 /* Examine the instruction before this one to make sure it is
3656 * not a skip type instruction */
3657 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3658 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3659 int b = cur_bank ^ REG_BANK(reg);
3661 //fprintf(stderr, "Cool! can switch banks\n");
3662 cur_bank = REG_BANK(reg);
3664 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3665 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3666 pCodeInsertAfter(pc->prev, new_pc);
3667 if(PCI(pc)->label) {
3668 PCI(new_pc)->label = PCI(pc)->label;
3669 PCI(pc)->label = NULL;
3672 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3673 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3674 pCodeInsertAfter(pc, new_pc);
3680 //fprintf(stderr, "Bummer can't switch banks\n");
3688 } while(pc && !(isPCFL(pc)));
3690 if(pcprev && cur_bank) {
3691 /* Brute force - make sure that we point to bank 0 at the
3692 * end of each flow block */
3693 new_pc = newpCode(POC_BCF,
3694 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3695 pCodeInsertAfter(pcprev, new_pc);
3703 void pBlockDestruct(pBlock *pb)
3714 /*-----------------------------------------------------------------*/
3715 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3716 /* name dbName and combine them */
3717 /* into one block */
3718 /*-----------------------------------------------------------------*/
3719 void mergepBlocks(char dbName)
3722 pBlock *pb, *pbmerged = NULL,*pbn;
3724 pb = the_pFile->pbHead;
3726 //fprintf(stderr," merging blocks named %c\n",dbName);
3730 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3731 if( getpBlock_dbName(pb) == dbName) {
3733 //fprintf(stderr," merged block %c\n",dbName);
3738 addpCode2pBlock(pbmerged, pb->pcHead);
3739 /* addpCode2pBlock doesn't handle the tail: */
3740 pbmerged->pcTail = pb->pcTail;
3742 pb->prev->next = pbn;
3744 pbn->prev = pb->prev;
3749 //printpBlock(stderr, pbmerged);
3756 /*-----------------------------------------------------------------*/
3757 /* AnalyzeBanking - Called after the memory addresses have been */
3758 /* assigned to the registers. */
3760 /*-----------------------------------------------------------------*/
3761 void AnalyzeBanking(void)
3770 /* Phase 2 - Flow Analysis
3772 * In this phase, the pCode is partition into pCodeFlow
3773 * blocks. The flow blocks mark the points where a continuous
3774 * stream of instructions changes flow (e.g. because of
3775 * a call or goto or whatever).
3778 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3781 /* Phase 2 - Flow Analysis - linking flow blocks
3783 * In this phase, the individual flow blocks are examined
3784 * to determine their order of excution.
3787 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3790 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3791 FixRegisterBanking(pb);
3794 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3796 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3797 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3798 pcflow = pcflow->next) {
3800 FillFlow(PCFL(pcflow));
3807 /*-----------------------------------------------------------------*/
3808 /* buildCallTree - look at the flow and extract all of the calls */
3810 /*-----------------------------------------------------------------*/
3811 set *register_usage(pBlock *pb);
3813 void buildCallTree(void )
3824 /* Now build the call tree.
3825 First we examine all of the pCodes for functions.
3826 Keep in mind that the function boundaries coincide
3827 with pBlock boundaries.
3829 The algorithm goes something like this:
3830 We have two nested loops. The outer loop iterates
3831 through all of the pBlocks/functions. The inner
3832 loop iterates through all of the pCodes for
3833 a given pBlock. When we begin iterating through
3834 a pBlock, the variable pc_fstart, pCode of the start
3835 of a function, is cleared. We then search for pCodes
3836 of type PC_FUNCTION. When one is encountered, we
3837 initialize pc_fstart to this and at the same time
3838 associate a new pBranch object that signifies a
3839 branch entry. If a return is found, then this signifies
3840 a function exit point. We'll link the pCodes of these
3841 returns to the matching pc_fstart.
3843 When we're done, a doubly linked list of pBranches
3844 will exist. The head of this list is stored in
3845 `the_pFile', which is the meta structure for all
3846 of the pCode. Look at the printCallTree function
3847 on how the pBranches are linked together.
3850 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3851 pCode *pc_fstart=NULL;
3852 for(pc = pb->pcHead; pc; pc = pc->next) {
3854 if (PCF(pc)->fname) {
3856 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3857 //fprintf(stderr," found main \n");
3858 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3862 pbr = Safe_calloc(1,sizeof(pBranch));
3863 pbr->pc = pc_fstart = pc;
3866 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3868 // Here's a better way of doing the same:
3869 addSet(&pb->function_entries, pc);
3872 // Found an exit point in a function, e.g. return
3873 // (Note, there may be more than one return per function)
3875 pBranchLink(PCF(pc_fstart), PCF(pc));
3877 addSet(&pb->function_exits, pc);
3879 } else if(isCALL(pc)) {
3880 addSet(&pb->function_calls,pc);
3885 /* Re-allocate the registers so that there are no collisions
3886 * between local variables when one function call another */
3888 pic14_deallocateAllRegs();
3890 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3897 /*-----------------------------------------------------------------*/
3898 /* AnalyzepCode - parse the pCode that has been generated and form */
3899 /* all of the logical connections. */
3901 /* Essentially what's done here is that the pCode flow is */
3903 /*-----------------------------------------------------------------*/
3905 void AnalyzepCode(char dbName)
3916 /* Phase 1 - Register allocation and peep hole optimization
3918 * The first part of the analysis is to determine the registers
3919 * that are used in the pCode. Once that is done, the peep rules
3920 * are applied to the code. We continue to loop until no more
3921 * peep rule optimizations are found (or until we exceed the
3922 * MAX_PASSES threshold).
3924 * When done, the required registers will be determined.
3930 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3932 /* First, merge the labels with the instructions */
3933 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3934 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3936 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3937 pBlockMergeLabels(pb);
3940 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
3944 changes = OptimizepCode(dbName);
3946 } while(changes && (i++ < MAX_PASSES));
3951 /*-----------------------------------------------------------------*/
3952 /* ispCodeFunction - returns true if *pc is the pCode of a */
3954 /*-----------------------------------------------------------------*/
3955 bool ispCodeFunction(pCode *pc)
3958 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3964 /*-----------------------------------------------------------------*/
3965 /* findFunction - Search for a function by name (given the name) */
3966 /* in the set of all functions that are in a pBlock */
3967 /* (note - I expect this to change because I'm planning to limit */
3968 /* pBlock's to just one function declaration */
3969 /*-----------------------------------------------------------------*/
3970 pCode *findFunction(char *fname)
3977 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3979 pc = setFirstItem(pb->function_entries);
3982 if((pc->type == PC_FUNCTION) &&
3984 (strcmp(fname, PCF(pc)->fname)==0))
3987 pc = setNextItem(pb->function_entries);
3995 void MarkUsedRegisters(set *regset)
4000 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4001 r2 = pic14_regWithIdx(r1->rIdx);
4007 void pBlockStats(FILE *of, pBlock *pb)
4013 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4015 // for now just print the first element of each set
4016 pc = setFirstItem(pb->function_entries);
4018 fprintf(of,";entry: ");
4021 pc = setFirstItem(pb->function_exits);
4023 fprintf(of,";has an exit\n");
4027 pc = setFirstItem(pb->function_calls);
4029 fprintf(of,";functions called:\n");
4032 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4033 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4035 pc = setNextItem(pb->function_calls);
4039 r = setFirstItem(pb->tregisters);
4041 int n = elementsInSet(pb->tregisters);
4043 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4046 fprintf(of,"; %s\n",r->name);
4047 r = setNextItem(pb->tregisters);
4052 /*-----------------------------------------------------------------*/
4053 /*-----------------------------------------------------------------*/
4054 static void sequencepCode(void)
4060 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4062 pb->seq = GpCodeSequenceNumber+1;
4064 for( pc = pb->pcHead; pc; pc = pc->next)
4065 pc->seq = ++GpCodeSequenceNumber;
4070 /*-----------------------------------------------------------------*/
4071 /*-----------------------------------------------------------------*/
4072 set *register_usage(pBlock *pb)
4075 set *registers=NULL;
4076 set *registersInCallPath = NULL;
4078 /* check recursion */
4080 pc = setFirstItem(pb->function_entries);
4087 if(pc->type != PC_FUNCTION)
4088 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4090 pc = setFirstItem(pb->function_calls);
4091 for( ; pc; pc = setNextItem(pb->function_calls)) {
4093 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4094 char *dest = get_op_from_instruction(PCI(pc));
4096 pcn = findFunction(dest);
4098 registersInCallPath = register_usage(pcn->pb);
4100 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4105 pBlockStats(stderr,pb); // debug
4108 // Mark the registers in this block as used.
4110 MarkUsedRegisters(pb->tregisters);
4111 if(registersInCallPath) {
4112 /* registers were used in the functions this pBlock has called */
4113 /* so now, we need to see if these collide with the ones we are */
4116 regs *r1,*r2, *newreg;
4118 DFPRINTF((stderr,"comparing registers\n"));
4120 r1 = setFirstItem(registersInCallPath);
4123 r2 = setFirstItem(pb->tregisters);
4125 while(r2 && (r1->type != REG_STK)) {
4127 if(r2->rIdx == r1->rIdx) {
4128 newreg = pic14_findFreeReg(REG_GPR);
4132 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4136 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4137 r1->rIdx, newreg->rIdx));
4138 r2->rIdx = newreg->rIdx;
4139 //if(r2->name) free(r2->name);
4141 r2->name = Safe_strdup(newreg->name);
4145 newreg->wasUsed = 1;
4147 r2 = setNextItem(pb->tregisters);
4150 r1 = setNextItem(registersInCallPath);
4153 /* Collisions have been resolved. Now free the registers in the call path */
4154 r1 = setFirstItem(registersInCallPath);
4156 if(r1->type != REG_STK) {
4157 newreg = pic14_regWithIdx(r1->rIdx);
4160 r1 = setNextItem(registersInCallPath);
4164 // MarkUsedRegisters(pb->registers);
4166 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4169 DFPRINTF((stderr,"returning regs\n"));
4171 DFPRINTF((stderr,"not returning regs\n"));
4173 DFPRINTF((stderr,"pBlock after register optim.\n"));
4174 pBlockStats(stderr,pb); // debug
4180 /*-----------------------------------------------------------------*/
4181 /* printCallTree - writes the call tree to a file */
4183 /*-----------------------------------------------------------------*/
4184 void pct2(FILE *of,pBlock *pb,int indent)
4188 // set *registersInCallPath = NULL;
4194 return; //recursion ?
4196 pc = setFirstItem(pb->function_entries);
4203 for(i=0;i<indent;i++) // Indentation
4206 if(pc->type == PC_FUNCTION)
4207 fprintf(of,"%s\n",PCF(pc)->fname);
4212 pc = setFirstItem(pb->function_calls);
4213 for( ; pc; pc = setNextItem(pb->function_calls)) {
4215 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4216 char *dest = get_op_from_instruction(PCI(pc));
4218 pcn = findFunction(dest);
4220 pct2(of,pcn->pb,indent+1);
4222 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4230 /*-----------------------------------------------------------------*/
4231 /* printCallTree - writes the call tree to a file */
4233 /*-----------------------------------------------------------------*/
4235 void printCallTree(FILE *of)
4247 fprintf(of, "\npBlock statistics\n");
4248 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4253 fprintf(of,"Call Tree\n");
4254 pbr = the_pFile->functions;
4258 if(!ispCodeFunction(pc))
4259 fprintf(of,"bug in call tree");
4262 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4264 while(pc->next && !ispCodeFunction(pc->next)) {
4266 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4267 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
4275 fprintf(of,"\n**************\n\na better call tree\n");
4276 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4281 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4282 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
4288 /*-----------------------------------------------------------------*/
4290 /*-----------------------------------------------------------------*/
4292 void InlineFunction(pBlock *pb)
4300 pc = setFirstItem(pb->function_calls);
4302 for( ; pc; pc = setNextItem(pb->function_calls)) {
4305 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
4311 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
4313 //fprintf(stderr,"Cool can inline:\n");
4314 //pcn->print(stderr,pcn);
4316 //fprintf(stderr,"recursive call Inline\n");
4317 InlineFunction(pcn->pb);
4318 //fprintf(stderr,"return from recursive call Inline\n");
4321 At this point, *pc points to a CALL mnemonic, and
4322 *pcn points to the function that is being called.
4324 To in-line this call, we need to remove the CALL
4325 and RETURN(s), and link the function pCode in with
4331 /* Remove the CALL */
4335 /* remove callee pBlock from the pBlock linked list */
4336 removepBlock(pcn->pb);
4344 /* Remove the Function pCode */
4345 pct = findNextInstruction(pcn->next);
4347 /* Link the function with the callee */
4348 pc->next = pcn->next;
4349 pcn->next->prev = pc;
4351 /* Convert the function name into a label */
4353 pbr = Safe_calloc(1,sizeof(pBranch));
4354 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
4356 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
4357 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
4359 /* turn all of the return's except the last into goto's */
4360 /* check case for 2 instruction pBlocks */
4361 pce = findNextInstruction(pcn->next);
4363 pCode *pce_next = findNextInstruction(pce->next);
4365 if(pce_next == NULL) {
4366 /* found the last return */
4367 pCode *pc_call_next = findNextInstruction(pc_call->next);
4369 //fprintf(stderr,"found last return\n");
4370 //pce->print(stderr,pce);
4371 pce->prev->next = pc_call->next;
4372 pc_call->next->prev = pce->prev;
4373 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
4383 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4389 /*-----------------------------------------------------------------*/
4391 /*-----------------------------------------------------------------*/
4393 void InlinepCode(void)
4403 /* Loop through all of the function definitions and count the
4404 * number of times each one is called */
4406 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4408 pc = setFirstItem(pb->function_calls);
4410 for( ; pc; pc = setNextItem(pb->function_calls)) {
4413 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
4414 if(pcn && isPCF(pcn)) {
4415 PCF(pcn)->ncalled++;
4418 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4424 /* Now, Loop through the function definitions again, but this
4425 * time inline those functions that have only been called once. */
4427 InlineFunction(the_pFile->pbHead);