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 = 1; /* Set true to inundate .asm file */
80 static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
87 extern int picIsInitialized(void);
89 /****************************************************************/
90 /* Forward declarations */
91 /****************************************************************/
93 void unlinkpCode(pCode *pc);
95 static void genericAnalyze(pCode *pc);
96 static void AnalyzeGOTO(pCode *pc);
97 static void AnalyzeSKIP(pCode *pc);
98 static void AnalyzeRETURN(pCode *pc);
101 static void genericDestruct(pCode *pc);
102 static void genericPrint(FILE *of,pCode *pc);
104 static void pCodePrintLabel(FILE *of, pCode *pc);
105 static void pCodePrintFunction(FILE *of, pCode *pc);
106 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
107 static char *get_op_from_instruction( pCodeInstruction *pcc);
108 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
109 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
110 int pCodePeepMatchRule(pCode *pc);
111 void pBlockStats(FILE *of, pBlock *pb);
112 pBlock *newpBlock(void);
113 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
114 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
115 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
116 void pCodeRegMapLiveRanges(pBlock *pb);
119 /****************************************************************/
120 /* PIC Instructions */
121 /****************************************************************/
123 pCodeInstruction pciADDWF = {
124 {PC_OPCODE, NULL, NULL, 0, NULL,
137 1,0, // dest, bit instruction
140 (PCC_W | PCC_REGISTER), // inCond
141 (PCC_REGISTER | PCC_Z) // outCond
144 pCodeInstruction pciADDFW = {
145 {PC_OPCODE, NULL, NULL, 0, NULL,
158 0,0, // dest, bit instruction
161 (PCC_W | PCC_REGISTER), // inCond
162 (PCC_W | PCC_Z) // outCond
165 pCodeInstruction pciADDLW = {
166 {PC_OPCODE, NULL, NULL, 0, NULL,
179 0,0, // dest, bit instruction
182 (PCC_W | PCC_LITERAL), // inCond
183 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
186 pCodeInstruction pciANDLW = {
187 {PC_OPCODE, NULL, NULL, 0, NULL,
200 0,0, // dest, bit instruction
203 (PCC_W | PCC_LITERAL), // inCond
204 (PCC_W | PCC_Z) // outCond
207 pCodeInstruction pciANDWF = {
208 {PC_OPCODE, NULL, NULL, 0, NULL,
221 1,0, // dest, bit instruction
224 (PCC_W | PCC_REGISTER), // inCond
225 (PCC_REGISTER | PCC_Z) // outCond
228 pCodeInstruction pciANDFW = {
229 {PC_OPCODE, NULL, NULL, 0, NULL,
242 0,0, // dest, bit instruction
245 (PCC_W | PCC_REGISTER), // inCond
246 (PCC_W | PCC_Z) // outCond
249 pCodeInstruction pciBCF = {
250 {PC_OPCODE, NULL, NULL, 0, NULL,
263 1,1, // dest, bit instruction
266 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
267 PCC_REGISTER // outCond
270 pCodeInstruction pciBSF = {
271 {PC_OPCODE, NULL, NULL, 0, NULL,
284 1,1, // dest, bit instruction
287 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
288 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
291 pCodeInstruction pciBTFSC = {
292 {PC_OPCODE, NULL, NULL, 0, NULL,
305 0,1, // dest, bit instruction
308 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
309 PCC_EXAMINE_PCOP // outCond
312 pCodeInstruction pciBTFSS = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,1, // dest, bit instruction
329 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
330 PCC_EXAMINE_PCOP // outCond
333 pCodeInstruction pciCALL = {
334 {PC_OPCODE, NULL, NULL, 0, NULL,
347 0,0, // dest, bit instruction
354 pCodeInstruction pciCOMF = {
355 {PC_OPCODE, NULL, NULL, 0, NULL,
368 1,0, // dest, bit instruction
371 PCC_REGISTER, // inCond
372 PCC_REGISTER // outCond
375 pCodeInstruction pciCOMFW = {
376 {PC_OPCODE, NULL, NULL, 0, NULL,
389 0,0, // dest, bit instruction
392 PCC_REGISTER, // inCond
396 pCodeInstruction pciCLRF = {
397 {PC_OPCODE, NULL, NULL, 0, NULL,
410 0,0, // dest, bit instruction
414 PCC_REGISTER // outCond
417 pCodeInstruction pciCLRW = {
418 {PC_OPCODE, NULL, NULL, 0, NULL,
431 0,0, // dest, bit instruction
438 pCodeInstruction pciDECF = {
439 {PC_OPCODE, NULL, NULL, 0, NULL,
452 1,0, // dest, bit instruction
455 PCC_REGISTER, // inCond
456 PCC_REGISTER // outCond
459 pCodeInstruction pciDECFW = {
460 {PC_OPCODE, NULL, NULL, 0, NULL,
473 0,0, // dest, bit instruction
476 PCC_REGISTER, // inCond
480 pCodeInstruction pciDECFSZ = {
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 1,0, // dest, bit instruction
497 PCC_REGISTER, // inCond
498 PCC_REGISTER // outCond
501 pCodeInstruction pciDECFSZW = {
502 {PC_OPCODE, NULL, NULL, 0, NULL,
515 0,0, // dest, bit instruction
518 PCC_REGISTER, // inCond
522 pCodeInstruction pciGOTO = {
523 {PC_OPCODE, NULL, NULL, 0, NULL,
536 0,0, // dest, bit instruction
543 pCodeInstruction pciINCF = {
544 {PC_OPCODE, NULL, NULL, 0, NULL,
557 1,0, // dest, bit instruction
560 PCC_REGISTER, // inCond
561 PCC_REGISTER // outCond
564 pCodeInstruction pciINCFW = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 0,0, // dest, bit instruction
581 PCC_REGISTER, // inCond
585 pCodeInstruction pciINCFSZ = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 1,0, // dest, bit instruction
602 PCC_REGISTER, // inCond
603 PCC_REGISTER // outCond
606 pCodeInstruction pciINCFSZW = {
607 {PC_OPCODE, NULL, NULL, 0, NULL,
620 0,0, // dest, bit instruction
623 PCC_REGISTER, // inCond
627 pCodeInstruction pciIORWF = {
628 {PC_OPCODE, NULL, NULL, 0, NULL,
641 1,0, // dest, bit instruction
644 (PCC_W | PCC_REGISTER), // inCond
645 (PCC_REGISTER | PCC_Z) // outCond
648 pCodeInstruction pciIORFW = {
649 {PC_OPCODE, NULL, NULL, 0, NULL,
662 0,0, // dest, bit instruction
665 (PCC_W | PCC_REGISTER), // inCond
666 (PCC_W | PCC_Z) // outCond
669 pCodeInstruction pciIORLW = {
670 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,0, // dest, bit instruction
686 (PCC_W | PCC_LITERAL), // inCond
687 (PCC_W | PCC_Z) // outCond
690 pCodeInstruction pciMOVF = {
691 {PC_OPCODE, NULL, NULL, 0, NULL,
704 1,0, // dest, bit instruction
707 PCC_REGISTER, // inCond
711 pCodeInstruction pciMOVFW = {
712 {PC_OPCODE, NULL, NULL, 0, NULL,
725 0,0, // dest, bit instruction
728 PCC_REGISTER, // inCond
729 (PCC_W | PCC_Z) // outCond
732 pCodeInstruction pciMOVWF = {
733 {PC_OPCODE, NULL, NULL, 0, NULL,
746 0,0, // dest, bit instruction
750 PCC_REGISTER // outCond
753 pCodeInstruction pciMOVLW = {
754 {PC_OPCODE, NULL, NULL, 0, NULL,
767 0,0, // dest, bit instruction
770 (PCC_NONE | PCC_LITERAL), // inCond
774 pCodeInstruction pciNOP = {
775 {PC_OPCODE, NULL, NULL, 0, NULL,
787 0,0, // dest, bit instruction
794 pCodeInstruction pciRETFIE = {
795 {PC_OPCODE, NULL, NULL, 0, NULL,
808 0,0, // dest, bit instruction
812 PCC_NONE // outCond (not true... affects the GIE bit too)
815 pCodeInstruction pciRETLW = {
816 {PC_OPCODE, NULL, NULL, 0, NULL,
829 0,0, // dest, bit instruction
832 PCC_LITERAL, // inCond
836 pCodeInstruction pciRETURN = {
837 {PC_OPCODE, NULL, NULL, 0, NULL,
850 0,0, // dest, bit instruction
857 pCodeInstruction pciRLF = {
858 {PC_OPCODE, NULL, NULL, 0, NULL,
871 1,0, // dest, bit instruction
874 (PCC_C | PCC_REGISTER), // inCond
875 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
878 pCodeInstruction pciRLFW = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
895 (PCC_C | PCC_REGISTER), // inCond
896 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
899 pCodeInstruction pciRRF = {
900 {PC_OPCODE, NULL, NULL, 0, NULL,
913 1,0, // dest, bit instruction
916 (PCC_C | PCC_REGISTER), // inCond
917 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
920 pCodeInstruction pciRRFW = {
921 {PC_OPCODE, NULL, NULL, 0, NULL,
934 0,0, // dest, bit instruction
937 (PCC_C | PCC_REGISTER), // inCond
938 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
941 pCodeInstruction pciSUBWF = {
942 {PC_OPCODE, NULL, NULL, 0, NULL,
955 1,0, // dest, bit instruction
958 (PCC_W | PCC_REGISTER), // inCond
959 (PCC_REGISTER | PCC_Z) // outCond
962 pCodeInstruction pciSUBFW = {
963 {PC_OPCODE, NULL, NULL, 0, NULL,
976 0,0, // dest, bit instruction
979 (PCC_W | PCC_REGISTER), // inCond
980 (PCC_W | PCC_Z) // outCond
983 pCodeInstruction pciSUBLW = {
984 {PC_OPCODE, NULL, NULL, 0, NULL,
997 0,0, // dest, bit instruction
1000 (PCC_W | PCC_LITERAL), // inCond
1001 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1004 pCodeInstruction pciSWAPF = {
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 1,0, // dest, bit instruction
1019 0,0, // branch, skip
1021 (PCC_REGISTER), // inCond
1022 (PCC_REGISTER) // outCond
1025 pCodeInstruction pciSWAPFW = {
1026 {PC_OPCODE, NULL, NULL, 0, NULL,
1032 NULL, // from branch
1039 0,0, // dest, bit instruction
1040 0,0, // branch, skip
1042 (PCC_REGISTER), // inCond
1046 pCodeInstruction pciTRIS = {
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 0,0, // branch, skip
1064 PCC_REGISTER // outCond
1067 pCodeInstruction pciXORWF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1084 (PCC_W | PCC_REGISTER), // inCond
1085 (PCC_REGISTER | PCC_Z) // outCond
1088 pCodeInstruction pciXORFW = {
1089 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 0,0, // dest, bit instruction
1103 0,0, // branch, skip
1105 (PCC_W | PCC_REGISTER), // inCond
1106 (PCC_W | PCC_Z) // outCond
1109 pCodeInstruction pciXORLW = {
1110 {PC_OPCODE, NULL, NULL, 0, NULL,
1116 NULL, // from branch
1123 0,0, // dest, bit instruction
1124 0,0, // branch, skip
1126 (PCC_W | PCC_LITERAL), // inCond
1127 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1131 #define MAX_PIC14MNEMONICS 100
1132 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1134 /* This definition needs to be part of configure.in */
1135 // #define USE_VSNPRINTF
1137 #ifdef USE_VSNPRINTF
1138 // Alas, vsnprintf is not ANSI standard, and does not exist
1139 // on Solaris (and probably other non-Gnu flavored Unixes).
1141 /*-----------------------------------------------------------------*/
1142 /* SAFE_snprintf - like snprintf except the string pointer is */
1143 /* after the string has been printed to. This is */
1144 /* useful for printing to string as though if it */
1145 /* were a stream. */
1146 /*-----------------------------------------------------------------*/
1147 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1155 va_start(val, format);
1157 vsnprintf(*str, *size, format, val);
1163 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1164 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1172 #else // USE_VSNPRINTF
1174 // This version is *not* safe, despite the name.
1176 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1180 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1185 va_start(val, format);
1187 vsprintf(buffer, format, val);
1190 len = strlen(buffer);
1192 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1193 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1196 strcpy(*str, buffer);
1202 #endif // USE_VSNPRINTF
1205 extern void initStack(int base_address, int size);
1206 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1207 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1208 extern void init_pic(char *);
1210 void pCodeInitRegisters(void)
1212 static int initialized=0;
1218 initStack(0xfff, 8);
1219 init_pic(port->processor);
1221 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1222 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1223 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1224 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1225 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1226 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1228 pc_status.rIdx = IDX_STATUS;
1229 pc_fsr.rIdx = IDX_FSR;
1230 pc_indf.rIdx = IDX_INDF;
1231 pc_intcon.rIdx = IDX_INTCON;
1232 pc_pcl.rIdx = IDX_PCL;
1233 pc_pclath.rIdx = IDX_PCLATH;
1235 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1236 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1237 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1239 pc_kzero.rIdx = IDX_KZ;
1240 pc_wsave.rIdx = IDX_WSAVE;
1241 pc_ssave.rIdx = IDX_SSAVE;
1243 /* probably should put this in a separate initialization routine */
1244 pb_dead_pcodes = newpBlock();
1248 /*-----------------------------------------------------------------*/
1249 /* mnem2key - convert a pic mnemonic into a hash key */
1250 /* (BTW - this spreads the mnemonics quite well) */
1252 /*-----------------------------------------------------------------*/
1254 int mnem2key(char const *mnem)
1263 key += toupper(*mnem++) +1;
1267 return (key & 0x1f);
1271 void pic14initMnemonics(void)
1276 pCodeInstruction *pci;
1278 if(mnemonics_initialized)
1281 //FIXME - probably should NULL out the array before making the assignments
1282 //since we check the array contents below this initialization.
1284 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1285 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1286 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1287 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1288 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1289 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1290 pic14Mnemonics[POC_BCF] = &pciBCF;
1291 pic14Mnemonics[POC_BSF] = &pciBSF;
1292 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1293 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1294 pic14Mnemonics[POC_CALL] = &pciCALL;
1295 pic14Mnemonics[POC_COMF] = &pciCOMF;
1296 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1297 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1298 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1299 pic14Mnemonics[POC_DECF] = &pciDECF;
1300 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1301 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1302 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1303 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1304 pic14Mnemonics[POC_INCF] = &pciINCF;
1305 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1306 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1307 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1308 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1309 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1310 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1311 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1312 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1313 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1314 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1315 pic14Mnemonics[POC_NOP] = &pciNOP;
1316 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1317 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1318 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1319 pic14Mnemonics[POC_RLF] = &pciRLF;
1320 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1321 pic14Mnemonics[POC_RRF] = &pciRRF;
1322 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1323 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1324 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1325 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1326 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1327 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1328 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1329 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1330 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1331 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1333 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1334 if(pic14Mnemonics[i])
1335 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1336 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1339 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1340 pci = hTabNextItem(pic14MnemonicsHash, &key);
1343 mnemonics_initialized = 1;
1346 int getpCodePeepCommand(char *cmd);
1348 int getpCode(char *mnem,unsigned dest)
1351 pCodeInstruction *pci;
1352 int key = mnem2key(mnem);
1354 if(!mnemonics_initialized)
1355 pic14initMnemonics();
1357 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1361 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1362 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1366 pci = hTabNextItemWK (pic14MnemonicsHash);
1373 /*-----------------------------------------------------------------*
1374 * pic14initpCodePeepCommands
1376 *-----------------------------------------------------------------*/
1377 void pic14initpCodePeepCommands(void)
1385 hTabAddItem(&pic14pCodePeepCommandsHash,
1386 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1388 } while (peepCommands[i].cmd);
1390 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1393 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1394 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1399 /*-----------------------------------------------------------------
1402 *-----------------------------------------------------------------*/
1404 int getpCodePeepCommand(char *cmd)
1408 int key = mnem2key(cmd);
1411 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1414 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1415 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1419 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1426 char getpBlock_dbName(pBlock *pb)
1432 return pb->cmemmap->dbName;
1436 void pBlockConvert2ISR(pBlock *pb)
1447 /*-----------------------------------------------------------------*/
1448 /* movepBlock2Head - given the dbname of a pBlock, move all */
1449 /* instances to the front of the doubly linked */
1450 /* list of pBlocks */
1451 /*-----------------------------------------------------------------*/
1453 void movepBlock2Head(char dbName)
1457 pb = the_pFile->pbHead;
1461 if(getpBlock_dbName(pb) == dbName) {
1462 pBlock *pbn = pb->next;
1463 pb->next = the_pFile->pbHead;
1464 the_pFile->pbHead->prev = pb;
1465 the_pFile->pbHead = pb;
1468 pb->prev->next = pbn;
1470 // If the pBlock that we just moved was the last
1471 // one in the link of all of the pBlocks, then we
1472 // need to point the tail to the block just before
1473 // the one we moved.
1474 // Note: if pb->next is NULL, then pb must have
1475 // been the last pBlock in the chain.
1478 pbn->prev = pb->prev;
1480 the_pFile->pbTail = pb->prev;
1491 void copypCode(FILE *of, char dbName)
1495 if(!of || !the_pFile)
1498 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1499 if(getpBlock_dbName(pb) == dbName) {
1506 void pcode_test(void)
1509 DFPRINTF((stderr,"pcode is alive!\n"));
1519 /* create the file name */
1520 strcpy(buffer,srcFileName);
1521 strcat(buffer,".p");
1523 if( !(pFile = fopen(buffer, "w" ))) {
1524 werror(E_FILE_OPEN_ERR,buffer);
1528 fprintf(pFile,"pcode dump\n\n");
1530 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1531 fprintf(pFile,"\n\tNew pBlock\n\n");
1533 fprintf(pFile,"%s",pb->cmemmap->sname);
1535 fprintf(pFile,"internal pblock");
1537 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1538 printpBlock(pFile,pb);
1542 /*-----------------------------------------------------------------*/
1543 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1544 /* ister, RegCond will return the bit being referenced. */
1546 /* fixme - why not just OR in the pcop bit field */
1547 /*-----------------------------------------------------------------*/
1549 static int RegCond(pCodeOp *pcop)
1555 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1556 switch(PCORB(pcop)->bit) {
1570 /*-----------------------------------------------------------------*/
1571 /* newpCode - create and return a newly initialized pCode */
1573 /* fixme - rename this */
1575 /* The purpose of this routine is to create a new Instruction */
1576 /* pCode. This is called by gen.c while the assembly code is being */
1580 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1581 /* (note that the op is analogous to but not the */
1582 /* same thing as the opcode of the instruction.) */
1583 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1586 /* a pointer to the new malloc'd pCode is returned. */
1590 /*-----------------------------------------------------------------*/
1591 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1593 pCodeInstruction *pci ;
1595 if(!mnemonics_initialized)
1596 pic14initMnemonics();
1598 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1600 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1601 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1604 if(pci->inCond & PCC_EXAMINE_PCOP)
1605 pci->inCond |= RegCond(pcop);
1607 if(pci->outCond & PCC_EXAMINE_PCOP)
1608 pci->outCond |= RegCond(pcop);
1610 pci->pc.prev = pci->pc.next = NULL;
1611 return (pCode *)pci;
1614 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1620 /*-----------------------------------------------------------------*/
1621 /* newpCodeWild - create a "wild" as in wild card pCode */
1623 /* Wild pcodes are used during the peep hole optimizer to serve */
1624 /* as place holders for any instruction. When a snippet of code is */
1625 /* compared to a peep hole rule, the wild card opcode will match */
1626 /* any instruction. However, the optional operand and label are */
1627 /* additional qualifiers that must also be matched before the */
1628 /* line (of assembly code) is declared matched. Note that the */
1629 /* operand may be wild too. */
1631 /* Note, a wild instruction is specified just like a wild var: */
1632 /* %4 ; A wild instruction, */
1633 /* See the peeph.def file for additional examples */
1635 /*-----------------------------------------------------------------*/
1637 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1642 pcw = Safe_calloc(1,sizeof(pCodeWild));
1644 pcw->pci.pc.type = PC_WILD;
1645 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1646 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1647 pcw->pci.pc.pb = NULL;
1649 // pcw->pci.pc.analyze = genericAnalyze;
1650 pcw->pci.pc.destruct = genericDestruct;
1651 pcw->pci.pc.print = genericPrint;
1653 pcw->id = pCodeID; // this is the 'n' in %n
1654 pcw->operand = optional_operand;
1655 pcw->label = optional_label;
1657 pcw->mustBeBitSkipInst = 0;
1658 pcw->mustNotBeBitSkipInst = 0;
1659 pcw->invertBitSkipInst = 0;
1661 return ( (pCode *)pcw);
1665 /*-----------------------------------------------------------------*/
1666 /* newPcodeInlineP - create a new pCode from a char string */
1667 /*-----------------------------------------------------------------*/
1670 pCode *newpCodeInlineP(char *cP)
1675 pcc = Safe_calloc(1,sizeof(pCodeComment));
1677 pcc->pc.type = PC_INLINE;
1678 pcc->pc.prev = pcc->pc.next = NULL;
1679 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1682 // pcc->pc.analyze = genericAnalyze;
1683 pcc->pc.destruct = genericDestruct;
1684 pcc->pc.print = genericPrint;
1687 pcc->comment = Safe_strdup(cP);
1689 pcc->comment = NULL;
1691 return ( (pCode *)pcc);
1695 /*-----------------------------------------------------------------*/
1696 /* newPcodeCharP - create a new pCode from a char string */
1697 /*-----------------------------------------------------------------*/
1699 pCode *newpCodeCharP(char *cP)
1704 pcc = Safe_calloc(1,sizeof(pCodeComment));
1706 pcc->pc.type = PC_COMMENT;
1707 pcc->pc.prev = pcc->pc.next = NULL;
1708 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1711 // pcc->pc.analyze = genericAnalyze;
1712 pcc->pc.destruct = genericDestruct;
1713 pcc->pc.print = genericPrint;
1716 pcc->comment = Safe_strdup(cP);
1718 pcc->comment = NULL;
1720 return ( (pCode *)pcc);
1724 /*-----------------------------------------------------------------*/
1725 /* newpCodeFunction - */
1726 /*-----------------------------------------------------------------*/
1729 pCode *newpCodeFunction(char *mod,char *f)
1733 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1734 //_ALLOC(pcf,sizeof(pCodeFunction));
1736 pcf->pc.type = PC_FUNCTION;
1737 pcf->pc.prev = pcf->pc.next = NULL;
1738 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1741 // pcf->pc.analyze = genericAnalyze;
1742 pcf->pc.destruct = genericDestruct;
1743 pcf->pc.print = pCodePrintFunction;
1748 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1749 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1750 strcpy(pcf->modname,mod);
1752 pcf->modname = NULL;
1755 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1756 pcf->fname = Safe_calloc(1,strlen(f)+1);
1757 strcpy(pcf->fname,f);
1761 return ( (pCode *)pcf);
1765 /*-----------------------------------------------------------------*/
1767 /*-----------------------------------------------------------------*/
1768 void destructpCodeFlow(pCode *pc)
1770 if(!pc || !isPCFL(pc))
1779 deleteSet(&PCFL(pc)->registers);
1780 deleteSet(&PCFL(pc)->from);
1781 deleteSet(&PCFL(pc)->to);
1786 pCode *newpCodeFlow(void )
1790 //_ALLOC(pcflow,sizeof(pCodeFlow));
1791 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1793 pcflow->pc.type = PC_FLOW;
1794 pcflow->pc.prev = pcflow->pc.next = NULL;
1795 pcflow->pc.pb = NULL;
1797 // pcflow->pc.analyze = genericAnalyze;
1798 pcflow->pc.destruct = destructpCodeFlow;
1799 pcflow->pc.print = genericPrint;
1801 pcflow->pc.seq = GpcFlowSeq++;
1803 pcflow->from = pcflow->to = NULL;
1805 pcflow->inCond = PCC_NONE;
1806 pcflow->outCond = PCC_NONE;
1808 pcflow->firstBank = -1;
1809 pcflow->lastBank = -1;
1811 pcflow->FromConflicts = 0;
1812 pcflow->ToConflicts = 0;
1816 pcflow->registers = newSet();
1818 return ( (pCode *)pcflow);
1822 /*-----------------------------------------------------------------*/
1823 /*-----------------------------------------------------------------*/
1824 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1826 pCodeFlowLink *pcflowLink;
1828 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1830 pcflowLink->pcflow = pcflow;
1831 pcflowLink->bank_conflict = 0;
1836 /*-----------------------------------------------------------------*/
1837 /* newpCodeCSource - create a new pCode Source Symbol */
1838 /*-----------------------------------------------------------------*/
1840 pCode *newpCodeCSource(int ln, char *f, char *l)
1845 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1847 pccs->pc.type = PC_CSOURCE;
1848 pccs->pc.prev = pccs->pc.next = NULL;
1851 pccs->pc.destruct = genericDestruct;
1852 pccs->pc.print = genericPrint;
1854 pccs->line_number = ln;
1856 pccs->line = Safe_strdup(l);
1861 pccs->file_name = Safe_strdup(f);
1863 pccs->file_name = NULL;
1865 return ( (pCode *)pccs);
1868 /*-----------------------------------------------------------------*/
1869 /* pCodeLabelDestruct - free memory used by a label. */
1870 /*-----------------------------------------------------------------*/
1871 static void pCodeLabelDestruct(pCode *pc)
1877 if((pc->type == PC_LABEL) && PCL(pc)->label)
1878 free(PCL(pc)->label);
1884 pCode *newpCodeLabel(char *name, int key)
1890 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1892 pcl->pc.type = PC_LABEL;
1893 pcl->pc.prev = pcl->pc.next = NULL;
1894 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1897 // pcl->pc.analyze = genericAnalyze;
1898 pcl->pc.destruct = pCodeLabelDestruct;
1899 pcl->pc.print = pCodePrintLabel;
1905 sprintf(s,"_%05d_DS_",key);
1910 pcl->label = Safe_strdup(s);
1913 return ( (pCode *)pcl);
1918 /*-----------------------------------------------------------------*/
1919 /* newpBlock - create and return a pointer to a new pBlock */
1920 /*-----------------------------------------------------------------*/
1921 pBlock *newpBlock(void)
1926 PpB = Safe_calloc(1,sizeof(pBlock) );
1927 PpB->next = PpB->prev = NULL;
1929 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1930 PpB->tregisters = NULL;
1932 PpB->FlowTree = NULL;
1938 /*-----------------------------------------------------------------*/
1939 /* newpCodeChain - create a new chain of pCodes */
1940 /*-----------------------------------------------------------------*
1942 * This function will create a new pBlock and the pointer to the
1943 * pCode that is passed in will be the first pCode in the block.
1944 *-----------------------------------------------------------------*/
1947 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1950 pBlock *pB = newpBlock();
1952 pB->pcHead = pB->pcTail = pc;
1959 /*-----------------------------------------------------------------*/
1960 /* newpCodeOpLabel - Create a new label given the key */
1961 /* Note, a negative key means that the label is part of wild card */
1962 /* (and hence a wild card label) used in the pCodePeep */
1963 /* optimizations). */
1964 /*-----------------------------------------------------------------*/
1966 pCodeOp *newpCodeOpLabel(char *name, int key)
1969 static int label_key=-1;
1973 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1974 pcop->type = PO_LABEL;
1979 sprintf(s=buffer,"_%05d_DS_",key);
1981 s = name, key = label_key--;
1984 pcop->name = Safe_strdup(s);
1986 ((pCodeOpLabel *)pcop)->key = key;
1991 /*-----------------------------------------------------------------*/
1992 /*-----------------------------------------------------------------*/
1993 pCodeOp *newpCodeOpLit(int lit)
1999 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2000 pcop->type = PO_LITERAL;
2004 sprintf(s,"0x%02x",lit);
2006 pcop->name = Safe_strdup(s);
2009 ((pCodeOpLit *)pcop)->lit = lit;
2014 /*-----------------------------------------------------------------*/
2015 /*-----------------------------------------------------------------*/
2016 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2020 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2021 pcop->type = PO_IMMEDIATE;
2023 regs *r = dirregWithName(name);
2024 pcop->name = Safe_strdup(name);
2027 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2028 PCOI(pcop)->rIdx = r->rIdx;
2030 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2031 PCOI(pcop)->rIdx = -1;
2033 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2038 PCOI(pcop)->index = index;
2039 PCOI(pcop)->offset = offset;
2040 PCOI(pcop)->_const = code_space;
2045 /*-----------------------------------------------------------------*/
2046 /*-----------------------------------------------------------------*/
2047 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2053 if(!pcwb || !subtype) {
2054 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2058 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2059 pcop->type = PO_WILD;
2060 sprintf(s,"%%%d",id);
2061 pcop->name = Safe_strdup(s);
2063 PCOW(pcop)->id = id;
2064 PCOW(pcop)->pcwb = pcwb;
2065 PCOW(pcop)->subtype = subtype;
2066 PCOW(pcop)->matched = NULL;
2071 /*-----------------------------------------------------------------*/
2072 /*-----------------------------------------------------------------*/
2073 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2077 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2078 pcop->type = PO_GPR_BIT;
2080 pcop->name = Safe_strdup(s);
2084 PCORB(pcop)->bit = bit;
2085 PCORB(pcop)->inBitSpace = inBitSpace;
2090 /*-----------------------------------------------------------------*
2091 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2093 * If rIdx >=0 then a specific register from the set of registers
2094 * will be selected. If rIdx <0, then a new register will be searched
2096 *-----------------------------------------------------------------*/
2098 pCodeOp *newpCodeOpReg(int rIdx)
2102 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2107 PCOR(pcop)->rIdx = rIdx;
2108 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2110 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2113 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2114 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2117 pcop->type = PCOR(pcop)->r->pc_type;
2122 pCodeOp *newpCodeOpRegFromStr(char *name)
2126 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2127 PCOR(pcop)->r = allocRegByName(name, 1);
2128 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2129 pcop->type = PCOR(pcop)->r->pc_type;
2130 pcop->name = PCOR(pcop)->r->name;
2135 /*-----------------------------------------------------------------*/
2136 /*-----------------------------------------------------------------*/
2138 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2145 pcop = newpCodeOpBit(name, -1,0);
2149 pcop = newpCodeOpLit(-1);
2153 pcop = newpCodeOpLabel(NULL,-1);
2156 pcop = newpCodeOpReg(-1);
2160 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2163 pcop->name = Safe_strdup(name);
2171 /*-----------------------------------------------------------------*/
2172 /*-----------------------------------------------------------------*/
2173 void pCodeConstString(char *name, char *value)
2177 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2182 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2186 sprintf(buffer,"; %s = %s",name,value);
2188 addpCode2pBlock(pb,newpCodeCharP(buffer));
2189 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2192 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2198 /*-----------------------------------------------------------------*/
2199 /*-----------------------------------------------------------------*/
2200 void pCodeReadCodeTable(void)
2204 fprintf(stderr, " %s\n",__FUNCTION__);
2206 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2210 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2211 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2212 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2213 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2215 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2216 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2217 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2218 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2223 /*-----------------------------------------------------------------*/
2224 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2225 /*-----------------------------------------------------------------*/
2226 void addpCode2pBlock(pBlock *pb, pCode *pc)
2233 /* If this is the first pcode to be added to a block that
2234 * was initialized with a NULL pcode, then go ahead and
2235 * make this pcode the head and tail */
2236 pb->pcHead = pb->pcTail = pc;
2239 pb->pcTail->next = pc;
2241 pc->prev = pb->pcTail;
2248 /*-----------------------------------------------------------------*/
2249 /* addpBlock - place a pBlock into the pFile */
2250 /*-----------------------------------------------------------------*/
2251 void addpBlock(pBlock *pb)
2253 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2256 /* First time called, we'll pass through here. */
2257 //_ALLOC(the_pFile,sizeof(pFile));
2258 the_pFile = Safe_calloc(1,sizeof(pFile));
2259 the_pFile->pbHead = the_pFile->pbTail = pb;
2260 the_pFile->functions = NULL;
2264 the_pFile->pbTail->next = pb;
2265 pb->prev = the_pFile->pbTail;
2267 the_pFile->pbTail = pb;
2270 /*-----------------------------------------------------------------*/
2271 /* removepBlock - remove a pBlock from the pFile */
2272 /*-----------------------------------------------------------------*/
2273 void removepBlock(pBlock *pb)
2281 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2283 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2286 if(pbs == the_pFile->pbHead)
2287 the_pFile->pbHead = pbs->next;
2289 if (pbs == the_pFile->pbTail)
2290 the_pFile->pbTail = pbs->prev;
2293 pbs->next->prev = pbs->prev;
2296 pbs->prev->next = pbs->next;
2303 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2307 /*-----------------------------------------------------------------*/
2308 /* printpCode - write the contents of a pCode to a file */
2309 /*-----------------------------------------------------------------*/
2310 void printpCode(FILE *of, pCode *pc)
2321 fprintf(of,"warning - unable to print pCode\n");
2324 /*-----------------------------------------------------------------*/
2325 /* printpBlock - write the contents of a pBlock to a file */
2326 /*-----------------------------------------------------------------*/
2327 void printpBlock(FILE *of, pBlock *pb)
2337 for(pc = pb->pcHead; pc; pc = pc->next)
2342 /*-----------------------------------------------------------------*/
2344 /* pCode processing */
2348 /*-----------------------------------------------------------------*/
2350 void unlinkpCode(pCode *pc)
2356 fprintf(stderr,"Unlinking: ");
2357 printpCode(stderr, pc);
2360 pc->prev->next = pc->next;
2362 pc->next->prev = pc->prev;
2364 pc->prev = pc->next = NULL;
2368 /*-----------------------------------------------------------------*/
2369 /*-----------------------------------------------------------------*/
2371 static void genericDestruct(pCode *pc)
2377 /* For instructions, tell the register (if there's one used)
2378 * that it's no longer needed */
2379 regs *reg = getRegFromInstruction(pc);
2381 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2384 /* Instead of deleting the memory used by this pCode, mark
2385 * the object as bad so that if there's a pointer to this pCode
2386 * dangling around somewhere then (hopefully) when the type is
2387 * checked we'll catch it.
2392 addpCode2pBlock(pb_dead_pcodes, pc);
2399 /*-----------------------------------------------------------------*/
2400 /*-----------------------------------------------------------------*/
2401 void pBlockRegs(FILE *of, pBlock *pb)
2406 r = setFirstItem(pb->tregisters);
2408 r = setNextItem(pb->tregisters);
2413 /*-----------------------------------------------------------------*/
2414 /*-----------------------------------------------------------------*/
2415 char *get_op(pCodeOp *pcop,char *buffer, int size)
2420 int use_buffer = 1; // copy the string to the passed buffer pointer
2425 use_buffer = 0; // Don't bother copying the string to the buffer.
2429 switch(pcop->type) {
2433 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2436 return PCOR(pcop)->r->name;
2439 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2442 SAFE_snprintf(&buffer,&size,"%s",r->name);
2452 if(PCOI(pcop)->_const) {
2454 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2455 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2458 8 * PCOI(pcop)->offset );
2460 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2463 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2464 SAFE_snprintf(&s,&size,"(%s + %d)",
2466 PCOI(pcop)->index );
2468 SAFE_snprintf(&s,&size,"%s",pcop->name);
2475 //size = sizeof(buffer);
2476 if( PCOR(pcop)->instance) {
2477 SAFE_snprintf(&s,&size,"(%s + %d)",
2479 PCOR(pcop)->instance );
2480 //fprintf(stderr,"PO_DIR %s\n",buffer);
2482 SAFE_snprintf(&s,&size,"%s",pcop->name);
2488 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2497 return "NO operand";
2501 /*-----------------------------------------------------------------*/
2502 /*-----------------------------------------------------------------*/
2503 static char *get_op_from_instruction( pCodeInstruction *pcc)
2507 return get_op(pcc->pcop,NULL,0);
2509 return ("ERROR Null: "__FUNCTION__);
2513 /*-----------------------------------------------------------------*/
2514 /*-----------------------------------------------------------------*/
2515 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2518 fprintf(of,"pcodeopprint- not implemented\n");
2521 /*-----------------------------------------------------------------*/
2522 /*-----------------------------------------------------------------*/
2523 char *pCode2str(char *str, int size, pCode *pc)
2531 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2533 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2535 if(PCI(pc)->isBitInst) {
2536 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2537 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2538 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2539 PCI(pc)->pcop->name ,
2540 PCI(pc)->pcop->name );
2542 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2543 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2544 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2545 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2547 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2548 //PCI(pc)->pcop->t.bit );
2551 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2552 if( PCI(pc)->num_ops == 2)
2553 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2555 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2558 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2560 if( PCI(pc)->num_ops == 2)
2561 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2569 /* assuming that comment ends with a \n */
2570 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2574 /* assuming that inline code ends with a \n */
2575 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2579 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2582 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2585 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2588 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2591 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2595 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2602 /*-----------------------------------------------------------------*/
2603 /* genericPrint - the contents of a pCode to a file */
2604 /*-----------------------------------------------------------------*/
2605 static void genericPrint(FILE *of, pCode *pc)
2613 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2617 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2621 // If the opcode has a label, print that first
2623 pBranch *pbl = PCI(pc)->label;
2624 while(pbl && pbl->pc) {
2625 if(pbl->pc->type == PC_LABEL)
2626 pCodePrintLabel(of, pbl->pc);
2632 genericPrint(of,PCODE(PCI(pc)->cline));
2637 pCode2str(str, 256, pc);
2639 fprintf(of,"%s",str);
2643 fprintf(of, "\t;key=%03x",pc->seq);
2645 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2650 pBranch *dpb = pc->to; // debug
2652 switch ( dpb->pc->type) {
2654 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2657 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2660 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2663 fprintf(of, "\t;flow");
2677 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2678 if(PCW(pc)->pci.label)
2679 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2681 if(PCW(pc)->operand) {
2682 fprintf(of,";\toperand ");
2683 pCodeOpPrint(of,PCW(pc)->operand );
2689 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2693 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2697 fprintf(of,"unknown pCode type %d\n",pc->type);
2702 /*-----------------------------------------------------------------*/
2703 /* pCodePrintFunction - prints function begin/end */
2704 /*-----------------------------------------------------------------*/
2706 static void pCodePrintFunction(FILE *of, pCode *pc)
2712 if( ((pCodeFunction *)pc)->modname)
2713 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2715 if(PCF(pc)->fname) {
2716 pBranch *exits = PCF(pc)->to;
2718 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2721 exits = exits->next;
2724 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2727 if((PCF(pc)->from &&
2728 PCF(pc)->from->pc->type == PC_FUNCTION &&
2729 PCF(PCF(pc)->from->pc)->fname) )
2730 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2732 fprintf(of,"; exit point [can't find entry point]\n");
2735 /*-----------------------------------------------------------------*/
2736 /* pCodePrintLabel - prints label */
2737 /*-----------------------------------------------------------------*/
2739 static void pCodePrintLabel(FILE *of, pCode *pc)
2746 fprintf(of,"%s\n",PCL(pc)->label);
2747 else if (PCL(pc)->key >=0)
2748 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2750 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2753 /*-----------------------------------------------------------------*/
2754 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2755 /* remove it if it is found. */
2756 /*-----------------------------------------------------------------*/
2757 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2764 if(pcl->type == PC_OPCODE)
2765 b = PCI(pcl)->label;
2767 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2772 //fprintf (stderr, "%s \n",__FUNCTION__);
2773 //pcl->print(stderr,pcl);
2774 //pc->print(stderr,pc);
2777 //fprintf (stderr, "found label\n");
2781 bprev->next = b->next; /* Not first pCode in chain */
2785 PCI(pcl)->label = b->next; /* First pCode in chain */
2788 return; /* A label can't occur more than once */
2796 /*-----------------------------------------------------------------*/
2797 /*-----------------------------------------------------------------*/
2798 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2817 /*-----------------------------------------------------------------*/
2818 /* pBranchLink - given two pcodes, this function will link them */
2819 /* together through their pBranches */
2820 /*-----------------------------------------------------------------*/
2821 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2825 // Declare a new branch object for the 'from' pCode.
2827 //_ALLOC(b,sizeof(pBranch));
2828 b = Safe_calloc(1,sizeof(pBranch));
2829 b->pc = PCODE(t); // The link to the 'to' pCode.
2832 f->to = pBranchAppend(f->to,b);
2834 // Now do the same for the 'to' pCode.
2836 //_ALLOC(b,sizeof(pBranch));
2837 b = Safe_calloc(1,sizeof(pBranch));
2841 t->from = pBranchAppend(t->from,b);
2846 /*-----------------------------------------------------------------*/
2847 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2849 /*-----------------------------------------------------------------*/
2850 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2863 /*-----------------------------------------------------------------*/
2864 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2865 /*-----------------------------------------------------------------*/
2866 static void pCodeUnlink(pCode *pc)
2871 if(!pc->prev || !pc->next) {
2872 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2876 /* first remove the pCode from the chain */
2877 pc->prev->next = pc->next;
2878 pc->next->prev = pc->prev;
2880 /* Now for the hard part... */
2882 /* Remove the branches */
2886 pc1 = pb1->pc; /* Get the pCode that branches to the
2887 * one we're unlinking */
2889 /* search for the link back to this pCode (the one we're
2891 if(pb2 = pBranchFind(pc1->to,pc)) {
2892 pb2->pc = pc->to->pc; // make the replacement
2894 /* if the pCode we're unlinking contains multiple 'to'
2895 * branches (e.g. this a skip instruction) then we need
2896 * to copy these extra branches to the chain. */
2898 pBranchAppend(pb2, pc->to->next);
2907 /*-----------------------------------------------------------------*/
2908 /*-----------------------------------------------------------------*/
2910 static void genericAnalyze(pCode *pc)
2920 // Go through the pCodes that are in pCode chain and link
2921 // them together through the pBranches. Note, the pCodes
2922 // are linked together as a contiguous stream like the
2923 // assembly source code lines. The linking here mimics this
2924 // except that comments are not linked in.
2926 pCode *npc = pc->next;
2928 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2929 pBranchLink(pc,npc);
2934 /* reached the end of the pcode chain without finding
2935 * an instruction we could link to. */
2939 fprintf(stderr,"analyze PC_FLOW\n");
2943 fprintf(stderr,,";A bad pCode is being used\n");
2949 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2955 if(pc->type == PC_LABEL) {
2956 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2959 if(pc->type == PC_OPCODE) {
2960 pbr = PCI(pc)->label;
2962 if(pbr->pc->type == PC_LABEL) {
2963 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2973 /*-----------------------------------------------------------------*/
2974 /*-----------------------------------------------------------------*/
2975 int checkLabel(pCode *pc)
2979 if(pc && isPCI(pc)) {
2980 pbr = PCI(pc)->label;
2982 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2992 /*-----------------------------------------------------------------*/
2993 /* findLabelinpBlock - Search the pCode for a particular label */
2994 /*-----------------------------------------------------------------*/
2995 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3002 for(pc = pb->pcHead; pc; pc = pc->next)
3003 if(compareLabel(pc,pcop_label))
3009 /*-----------------------------------------------------------------*/
3010 /* findLabel - Search the pCode for a particular label */
3011 /*-----------------------------------------------------------------*/
3012 pCode * findLabel(pCodeOpLabel *pcop_label)
3020 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3021 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3025 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3029 /*-----------------------------------------------------------------*/
3030 /* findNextpCode - given a pCode, find the next of type 'pct' */
3031 /* in the linked list */
3032 /*-----------------------------------------------------------------*/
3033 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3046 /*-----------------------------------------------------------------*/
3047 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3048 /* in the linked list */
3049 /*-----------------------------------------------------------------*/
3050 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3062 /*-----------------------------------------------------------------*/
3063 /* findNextInstruction - given a pCode, find the next instruction */
3064 /* in the linked list */
3065 /*-----------------------------------------------------------------*/
3066 pCode * findNextInstruction(pCode *pci)
3071 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3075 fprintf(stderr,"findNextInstruction: ");
3076 printpCode(stderr, pc);
3081 //fprintf(stderr,"Couldn't find instruction\n");
3085 /*-----------------------------------------------------------------*/
3086 /* findNextInstruction - given a pCode, find the next instruction */
3087 /* in the linked list */
3088 /*-----------------------------------------------------------------*/
3089 pCode * findPrevInstruction(pCode *pci)
3091 return findPrevpCode(pci, PC_OPCODE);
3094 /*-----------------------------------------------------------------*/
3095 /* findFunctionEnd - given a pCode find the end of the function */
3096 /* that contains it */
3097 /*-----------------------------------------------------------------*/
3098 pCode * findFunctionEnd(pCode *pc)
3102 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3108 fprintf(stderr,"Couldn't find function end\n");
3113 /*-----------------------------------------------------------------*/
3114 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3115 /* instruction with which it is associated. */
3116 /*-----------------------------------------------------------------*/
3117 static void AnalyzeLabel(pCode *pc)
3126 static void AnalyzeGOTO(pCode *pc)
3129 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3133 static void AnalyzeSKIP(pCode *pc)
3136 pBranchLink(pc,findNextInstruction(pc->next));
3137 pBranchLink(pc,findNextInstruction(pc->next->next));
3141 static void AnalyzeRETURN(pCode *pc)
3144 // branch_link(pc,findFunctionEnd(pc->next));
3150 /*-----------------------------------------------------------------*/
3151 /*-----------------------------------------------------------------*/
3152 regs * getRegFromInstruction(pCode *pc)
3158 PCI(pc)->num_ops == 0 )
3161 switch(PCI(pc)->pcop->type) {
3164 return PCOR(PCI(pc)->pcop)->r;
3166 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3170 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3171 return PCOR(PCI(pc)->pcop)->r;
3174 if(PCOI(PCI(pc)->pcop)->r)
3175 return (PCOI(PCI(pc)->pcop)->r);
3177 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3178 return dirregWithName(PCI(pc)->pcop->name);
3179 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3182 return PCOR(PCI(pc)->pcop)->r;
3185 //fprintf(stderr, "getRegFromInstruction - dir\n");
3186 return PCOR(PCI(pc)->pcop)->r;
3188 //fprintf(stderr, "getRegFromInstruction - literal\n");
3192 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3193 //genericPrint(stderr, pc);
3201 /*-----------------------------------------------------------------*/
3202 /*-----------------------------------------------------------------*/
3204 void AnalyzepBlock(pBlock *pb)
3211 /* Find all of the registers used in this pBlock
3212 * by looking at each instruction and examining it's
3215 for(pc = pb->pcHead; pc; pc = pc->next) {
3217 /* Is this an instruction with operands? */
3218 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3220 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3222 /* Loop through all of the registers declared so far in
3223 this block and see if we find this one there */
3225 regs *r = setFirstItem(pb->tregisters);
3228 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3229 PCOR(PCI(pc)->pcop)->r = r;
3232 r = setNextItem(pb->tregisters);
3236 /* register wasn't found */
3237 //r = Safe_calloc(1, sizeof(regs));
3238 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3239 //addSet(&pb->tregisters, r);
3240 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3241 //PCOR(PCI(pc)->pcop)->r = r;
3242 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3244 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3247 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3248 if(PCOR(PCI(pc)->pcop)->r) {
3249 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3250 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3252 if(PCI(pc)->pcop->name)
3253 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3255 fprintf(stderr,"ERROR: NULL register\n");
3264 /*-----------------------------------------------------------------*/
3266 /*-----------------------------------------------------------------*/
3267 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3269 void InsertpFlow(pCode *pc, pCode **pflow)
3272 PCFL(*pflow)->end = pc;
3274 if(!pc || !pc->next)
3277 *pflow = newpCodeFlow();
3278 pCodeInsertAfter(pc, *pflow);
3281 /*-----------------------------------------------------------------*/
3282 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3283 /* the flow blocks. */
3285 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3286 * point the instruction flow changes.
3288 /*-----------------------------------------------------------------*/
3289 void BuildFlow(pBlock *pb)
3292 pCode *last_pci=NULL;
3299 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3300 /* Insert a pCodeFlow object at the beginning of a pBlock */
3302 InsertpFlow(pb->pcHead, &pflow);
3304 //pflow = newpCodeFlow(); /* Create a new Flow object */
3305 //pflow->next = pb->pcHead; /* Make the current head the next object */
3306 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3307 //pb->pcHead = pflow; /* Make the Flow object the head */
3310 for( pc = findNextInstruction(pb->pcHead);
3312 pc=findNextInstruction(pc)) {
3315 PCI(pc)->pcflow = PCFL(pflow);
3317 //fprintf(stderr," build: ");
3318 //pflow->print(stderr,pflow);
3320 if( PCI(pc)->isSkip) {
3322 /* The two instructions immediately following this one
3323 * mark the beginning of a new flow segment */
3325 while(pc && PCI(pc)->isSkip) {
3327 PCI(pc)->pcflow = PCFL(pflow);
3331 InsertpFlow(pc, &pflow);
3332 pc=findNextInstruction(pc->next);
3340 PCI(pc)->pcflow = PCFL(pflow);
3342 InsertpFlow(pc, &pflow);
3344 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3346 InsertpFlow(pc, &pflow);
3349 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3351 /* This instruction marks the beginning of a
3352 * new flow segment */
3356 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3358 PCI(pc)->pcflow = PCFL(pflow);
3365 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3367 PCFL(pflow)->end = pb->pcTail;
3370 /*-------------------------------------------------------------------*/
3371 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3372 /* the flow blocks. */
3374 * unBuildFlow removes pCodeFlow objects from a pCode chain
3376 /*-----------------------------------------------------------------*/
3377 void unBuildFlow(pBlock *pb)
3392 if(PCI(pc)->pcflow) {
3393 //free(PCI(pc)->pcflow);
3394 PCI(pc)->pcflow = NULL;
3397 } else if(isPCFL(pc) )
3406 /*-----------------------------------------------------------------*/
3407 /*-----------------------------------------------------------------*/
3408 void dumpCond(int cond)
3411 static char *pcc_str[] = {
3425 int ncond = sizeof(pcc_str) / sizeof(char *);
3428 fprintf(stderr, "0x%04X\n",cond);
3430 for(i=0,j=1; i<ncond; i++, j<<=1)
3432 fprintf(stderr, " %s\n",pcc_str[i]);
3436 /*-----------------------------------------------------------------*/
3437 /*-----------------------------------------------------------------*/
3438 void FlowStats(pCodeFlow *pcflow)
3446 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3448 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3451 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3456 fprintf(stderr, " FlowStats inCond: ");
3457 dumpCond(pcflow->inCond);
3458 fprintf(stderr, " FlowStats outCond: ");
3459 dumpCond(pcflow->outCond);
3463 /*-----------------------------------------------------------------*
3464 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3465 * if it affects the banking bits.
3467 * return: -1 == Banking bits are unaffected by this pCode.
3469 * return: > 0 == Banking bits are affected.
3471 * If the banking bits are affected, then the returned value describes
3472 * which bits are affected and how they're affected. The lower half
3473 * of the integer maps to the bits that are affected, the upper half
3474 * to whether they're set or cleared.
3476 *-----------------------------------------------------------------*/
3477 #define SET_BANK_BIT (1 << 16)
3478 #define CLR_BANK_BIT 0
3480 int isBankInstruction(pCode *pc)
3488 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3490 /* Check to see if the register banks are changing */
3491 if(PCI(pc)->isModReg) {
3493 pCodeOp *pcop = PCI(pc)->pcop;
3494 switch(PCI(pc)->op) {
3497 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3498 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3499 return SET_BANK_BIT | PIC_RP0_BIT;
3502 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3503 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3504 return CLR_BANK_BIT | PIC_RP0_BIT;
3509 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3510 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3511 return CLR_BANK_BIT | PIC_RP1_BIT;
3513 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3514 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3515 return CLR_BANK_BIT | PIC_RP1_BIT;
3519 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3520 //genericPrint(stderr, pc);
3531 /*-----------------------------------------------------------------*/
3532 /*-----------------------------------------------------------------*/
3533 void FillFlow(pCodeFlow *pcflow)
3542 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3544 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3547 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3554 isBankInstruction(pc);
3556 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3560 fprintf(stderr, " FillFlow - Bad end of flow\n");
3562 fprintf(stderr, " FillFlow - Ending flow with\n ");
3563 pc->print(stderr,pc);
3566 fprintf(stderr, " FillFlow inCond: ");
3567 dumpCond(pcflow->inCond);
3568 fprintf(stderr, " FillFlow outCond: ");
3569 dumpCond(pcflow->outCond);
3573 /*-----------------------------------------------------------------*/
3574 /*-----------------------------------------------------------------*/
3575 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3577 pCodeFlowLink *fromLink, *toLink;
3579 if(!from || !to || !to->pcflow || !from->pcflow)
3582 fromLink = newpCodeFlowLink(from->pcflow);
3583 toLink = newpCodeFlowLink(to->pcflow);
3585 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3586 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3590 /*-----------------------------------------------------------------*/
3591 /*-----------------------------------------------------------------*/
3592 void LinkFlow(pBlock *pb)
3598 //fprintf(stderr,"linkflow \n");
3600 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3602 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3605 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3607 //fprintf(stderr," link: ");
3608 //pcflow->print(stderr,pcflow);
3610 //FillFlow(PCFL(pcflow));
3612 pc = PCFL(pcflow)->end;
3614 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3615 if(isPCI_SKIP(pc)) {
3616 //fprintf(stderr, "ends with skip\n");
3617 //pc->print(stderr,pc);
3618 pct=findNextInstruction(pc->next);
3619 LinkFlow_pCode(PCI(pc),PCI(pct));
3620 pct=findNextInstruction(pct->next);
3621 LinkFlow_pCode(PCI(pc),PCI(pct));
3625 if(isPCI_BRANCH(pc)) {
3626 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3628 //fprintf(stderr, "ends with branch\n ");
3629 //pc->print(stderr,pc);
3631 if(!(pcol && isPCOLAB(pcol))) {
3632 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3633 pc->print(stderr,pc);
3634 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3639 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3640 LinkFlow_pCode(PCI(pc),PCI(pct));
3642 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3648 //fprintf(stderr, "ends with non-branching instruction:\n");
3649 //pc->print(stderr,pc);
3651 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3657 //fprintf(stderr, "ends with unknown\n");
3658 //pc->print(stderr,pc);
3662 //fprintf(stderr, "ends with nothing: ERROR\n");
3667 /*-----------------------------------------------------------------*/
3668 /*-----------------------------------------------------------------*/
3669 int isPCinFlow(pCode *pc, pCode *pcflow)
3675 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3678 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3684 /*-----------------------------------------------------------------*/
3685 /*-----------------------------------------------------------------*/
3686 void BanksUsedFlow2(pCode *pcflow)
3695 if(!isPCFL(pcflow)) {
3696 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3700 pc = findNextInstruction(pcflow->next);
3702 PCFL(pcflow)->lastBank = -1;
3704 while(isPCinFlow(pc,pcflow)) {
3706 int bank_selected = isBankInstruction(pc);
3708 //if(PCI(pc)->pcflow)
3709 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3711 if(bank_selected > 0) {
3712 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3714 /* This instruction is modifying banking bits before accessing registers */
3716 PCFL(pcflow)->firstBank = -1;
3718 if(PCFL(pcflow)->lastBank == -1)
3719 PCFL(pcflow)->lastBank = 0;
3721 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3722 if(bank_selected & SET_BANK_BIT)
3723 PCFL(pcflow)->lastBank |= bank;
3727 reg = getRegFromInstruction(pc);
3729 if(reg && !isREGinBank(reg, bank)) {
3730 int allbanks = REGallBanks(reg);
3732 PCFL(pcflow)->firstBank = allbanks;
3734 PCFL(pcflow)->lastBank = allbanks;
3741 pc = findNextInstruction(pc->next);
3744 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3745 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3750 /*-----------------------------------------------------------------*/
3751 /*-----------------------------------------------------------------*/
3752 void BanksUsedFlow(pBlock *pb)
3757 //pb->pcHead->print(stderr, pb->pcHead);
3759 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3760 //pcflow->print(stderr,pcflow);
3762 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3764 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3766 BanksUsedFlow2(pcflow);
3772 /*-----------------------------------------------------------------*/
3773 /*-----------------------------------------------------------------*/
3774 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3782 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3784 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3785 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3787 pCodeInsertAfter(pc->prev, new_pc);
3789 /* Move the label, if there is one */
3791 if(PCI(pc)->label) {
3792 PCI(new_pc)->label = PCI(pc)->label;
3793 PCI(pc)->label = NULL;
3796 /* The new instruction has the same pcflow block */
3797 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3800 /*-----------------------------------------------------------------*/
3801 /*-----------------------------------------------------------------*/
3802 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3813 pc = findNextInstruction(pcfl->pc.next);
3815 while(isPCinFlow(pc,PCODE(pcfl))) {
3818 reg = getRegFromInstruction(pc);
3821 fprintf(stderr, " %s ",reg->name);
3822 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3827 if(reg && REG_BANK(reg)!=cur_bank) {
3828 /* Examine the instruction before this one to make sure it is
3829 * not a skip type instruction */
3830 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3831 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3832 int b = cur_bank ^ REG_BANK(reg);
3834 //fprintf(stderr, "Cool! can switch banks\n");
3835 cur_bank = REG_BANK(reg);
3840 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3843 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3844 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3848 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3849 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3851 insertBankSwitch(pc, -1, -1);
3854 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3855 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3856 pCodeInsertAfter(pc->prev, new_pc);
3857 if(PCI(pc)->label) {
3858 PCI(new_pc)->label = PCI(pc)->label;
3859 PCI(pc)->label = NULL;
3863 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3864 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3865 pCodeInsertAfter(pc, new_pc);
3871 //fprintf(stderr, "Bummer can't switch banks\n");
3877 pc = findNextInstruction(pc->next);
3881 if(pcprev && cur_bank) {
3882 /* Brute force - make sure that we point to bank 0 at the
3883 * end of each flow block */
3884 new_pc = newpCode(POC_BCF,
3885 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3886 pCodeInsertAfter(pcprev, new_pc);
3892 /*-----------------------------------------------------------------*/
3893 /*int compareBankFlow - compare the banking requirements between */
3895 /*-----------------------------------------------------------------*/
3896 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3899 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3902 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3905 if(pcflow->firstBank == -1)
3909 if(pcflowLink->pcflow->firstBank == -1) {
3910 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3911 pcflowLink->pcflow->to :
3912 pcflowLink->pcflow->from);
3913 return compareBankFlow(pcflow, pctl, toORfrom);
3917 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3920 pcflowLink->bank_conflict++;
3921 pcflowLink->pcflow->FromConflicts++;
3922 pcflow->ToConflicts++;
3925 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3928 pcflowLink->bank_conflict++;
3929 pcflowLink->pcflow->ToConflicts++;
3930 pcflow->FromConflicts++;
3934 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3935 pcflowLink->pcflow->pc.seq,
3936 pcflowLink->pcflow->FromConflicts,
3937 pcflowLink->pcflow->ToConflicts);
3942 /*-----------------------------------------------------------------*/
3943 /*-----------------------------------------------------------------*/
3944 void FixBankFlow(pBlock *pb)
3948 pCodeFlowLink *pcfl;
3950 pCode *pcflow_max_To=NULL;
3951 pCode *pcflow_max_From=NULL;
3952 int max_ToConflicts=0;
3953 int max_FromConflicts=0;
3955 //fprintf(stderr,"Fix Bank flow \n");
3956 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3960 First loop through all of the flow objects in this pcode block
3961 and fix the ones that have banking conflicts between the
3965 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3967 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3969 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3971 if(!isPCFL(pcflow)) {
3972 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3976 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3977 PCFL(pcflow)->firstBank >= 0 &&
3978 PCFL(pcflow)->lastBank >= 0 ) {
3980 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3981 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3983 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3984 BanksUsedFlow2(pcflow);
3989 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3991 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3993 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3998 if(!isPCFL(pcflow)) {
3999 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4003 PCFL(pcflow)->FromConflicts = 0;
4004 PCFL(pcflow)->ToConflicts = 0;
4009 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4010 pcfl = setFirstItem(PCFL(pcflow)->from);
4013 pc = PCODE(pcfl->pcflow);
4016 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4017 pc->print(stderr,pc);
4020 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4023 pcfl=setNextItem(PCFL(pcflow)->from);
4026 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4027 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4029 FixRegisterBankingInFlow(PCFL(pcflow),0);
4030 BanksUsedFlow2(pcflow);
4032 continue; /* Don't need to check the flow from here - it's already been fixed */
4039 pcfl = setFirstItem(PCFL(pcflow)->to);
4042 pc = PCODE(pcfl->pcflow);
4044 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4045 pc->print(stderr,pc);
4048 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4051 pcfl=setNextItem(PCFL(pcflow)->to);
4054 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4055 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4057 FixRegisterBankingInFlow(PCFL(pcflow),0);
4058 BanksUsedFlow2(pcflow);
4063 Loop through the flow objects again and find the ones with the
4067 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4069 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4071 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4072 pcflow_max_To = pcflow;
4074 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4075 pcflow_max_From = pcflow;
4079 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4080 PCFL(pcflow_max_To)->pc.seq,
4081 PCFL(pcflow_max_To)->ToConflicts);
4084 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4085 PCFL(pcflow_max_From)->pc.seq,
4086 PCFL(pcflow_max_From)->FromConflicts);
4090 /*-----------------------------------------------------------------*/
4091 /*-----------------------------------------------------------------*/
4092 void DumpFlow(pBlock *pb)
4096 pCodeFlowLink *pcfl;
4099 fprintf(stderr,"Dump flow \n");
4100 pb->pcHead->print(stderr, pb->pcHead);
4102 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4103 pcflow->print(stderr,pcflow);
4105 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4107 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4109 if(!isPCFL(pcflow)) {
4110 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4113 fprintf(stderr,"dumping: ");
4114 pcflow->print(stderr,pcflow);
4115 FlowStats(PCFL(pcflow));
4117 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4119 pc = PCODE(pcfl->pcflow);
4121 fprintf(stderr, " from seq %d:\n",pc->seq);
4123 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4124 pc->print(stderr,pc);
4129 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4131 pc = PCODE(pcfl->pcflow);
4133 fprintf(stderr, " to seq %d:\n",pc->seq);
4135 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4136 pc->print(stderr,pc);
4145 /*-----------------------------------------------------------------*/
4146 /*-----------------------------------------------------------------*/
4147 int OptimizepBlock(pBlock *pb)
4152 if(!pb || !peepOptimizing)
4155 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4157 for(pc = pb->pcHead; pc; pc = pc->next)
4158 matches += pCodePeepMatchRule(pc);
4161 pc = findNextInstruction(pb->pcHead);
4169 if(pCodePeepMatchRule(pc)) {
4174 pc = findNextInstruction(pcprev->next);
4176 pc = findNextInstruction(pb->pcHead);
4178 pc = findNextInstruction(pc->next);
4182 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4187 /*-----------------------------------------------------------------*/
4188 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4189 /*-----------------------------------------------------------------*/
4190 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4194 for(pc = pcs; pc; pc = pc->next) {
4196 if((pc->type == PC_OPCODE) &&
4198 (PCI(pc)->pcop->type == PO_LABEL) &&
4199 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4207 /*-----------------------------------------------------------------*/
4208 /*-----------------------------------------------------------------*/
4209 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4214 (PCI(pc)->pcop->type == PO_LABEL)) {
4216 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4218 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4220 free(pcol->pcop.name);
4222 sprintf(buffer,"_%05d_DS_",pcl->key);
4224 pcol->pcop.name = Safe_strdup(buffer);
4225 pcol->key = pcl->key;
4226 //pc->print(stderr,pc);
4233 /*-----------------------------------------------------------------*/
4234 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4235 /* pCode chain if they're not used. */
4236 /*-----------------------------------------------------------------*/
4237 void pBlockRemoveUnusedLabels(pBlock *pb)
4239 pCode *pc; pCodeLabel *pcl;
4244 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4246 pBranch *pbr = PCI(pc)->label;
4247 if(pbr && pbr->next) {
4248 pCode *pcd = pb->pcHead;
4250 //fprintf(stderr, "multiple labels\n");
4251 //pc->print(stderr,pc);
4256 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4257 //fprintf(stderr,"Used by:\n");
4258 //pcd->print(stderr,pcd);
4260 exchangeLabels(PCL(pbr->pc),pcd);
4269 for(pc = pb->pcHead; pc; pc = pc->next) {
4271 if(isPCL(pc)) // pc->type == PC_LABEL)
4273 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4274 pcl = PCL(PCI(pc)->label->pc);
4277 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4279 /* This pCode is a label, so search the pBlock to see if anyone
4282 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4283 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4284 /* Couldn't find an instruction that refers to this label
4285 * So, unlink the pCode label from it's pCode chain
4286 * and destroy the label */
4287 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4289 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4290 if(pc->type == PC_LABEL) {
4292 pCodeLabelDestruct(pc);
4294 unlinkpCodeFromBranch(pc, PCODE(pcl));
4295 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4306 /*-----------------------------------------------------------------*/
4307 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4308 /* chain and put them into pBranches that are */
4309 /* associated with the appropriate pCode */
4311 /*-----------------------------------------------------------------*/
4312 void pBlockMergeLabels(pBlock *pb)
4315 pCode *pc, *pcnext=NULL;
4320 /* First, Try to remove any unused labels */
4321 //pBlockRemoveUnusedLabels(pb);
4323 /* Now loop through the pBlock and merge the labels with the opcodes */
4326 // for(pc = pb->pcHead; pc; pc = pc->next) {
4329 pCode *pcn = pc->next;
4331 if(pc->type == PC_LABEL) {
4333 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4334 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4335 if((pcnext = findNextInstruction(pc) )) {
4337 // Unlink the pCode label from it's pCode chain
4340 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4341 // And link it into the instruction's pBranch labels. (Note, since
4342 // it's possible to have multiple labels associated with one instruction
4343 // we must provide a means to accomodate the additional labels. Thus
4344 // the labels are placed into the singly-linked list "label" as
4345 // opposed to being a single member of the pCodeInstruction.)
4347 //_ALLOC(pbr,sizeof(pBranch));
4348 pbr = Safe_calloc(1,sizeof(pBranch));
4352 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4355 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4357 } else if(pc->type == PC_CSOURCE) {
4359 /* merge the source line symbolic info into the next instruction */
4360 if((pcnext = findNextInstruction(pc) )) {
4362 // Unlink the pCode label from it's pCode chain
4364 PCI(pcnext)->cline = PCCS(pc);
4365 //fprintf(stderr, "merging CSRC\n");
4366 //genericPrint(stderr,pcnext);
4372 pBlockRemoveUnusedLabels(pb);
4376 /*-----------------------------------------------------------------*/
4377 /*-----------------------------------------------------------------*/
4378 int OptimizepCode(char dbName)
4380 #define MAX_PASSES 4
4389 DFPRINTF((stderr," Optimizing pCode\n"));
4393 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4394 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4395 matches += OptimizepBlock(pb);
4398 while(matches && ++passes < MAX_PASSES);
4403 /*-----------------------------------------------------------------*/
4404 /* popCopyGPR2Bit - copy a pcode operator */
4405 /*-----------------------------------------------------------------*/
4407 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4411 pcop = newpCodeOpBit(pc->name, bitval, 0);
4413 if( !( (pcop->type == PO_LABEL) ||
4414 (pcop->type == PO_LITERAL) ||
4415 (pcop->type == PO_STR) ))
4416 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4424 /*-----------------------------------------------------------------*/
4425 /*-----------------------------------------------------------------*/
4426 int InstructionRegBank(pCode *pc)
4430 if( (reg = getRegFromInstruction(pc)) == NULL)
4433 return REG_BANK(reg);
4438 /*-----------------------------------------------------------------*/
4439 /*-----------------------------------------------------------------*/
4440 void FixRegisterBanking(pBlock *pb)
4452 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4453 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4456 /* loop through all of the flow blocks with in one pblock */
4458 //fprintf(stderr,"Register banking\n");
4461 /* at this point, pc should point to a PC_FLOW object */
4464 /* for each flow block, determine the register banking
4469 //genericPrint(stderr, pc);
4471 reg = getRegFromInstruction(pc);
4474 fprintf(stderr, " %s ",reg->name);
4475 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4479 if(reg && REG_BANK(reg)!=cur_bank) {
4480 /* Examine the instruction before this one to make sure it is
4481 * not a skip type instruction */
4482 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4483 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4484 int b = cur_bank ^ REG_BANK(reg);
4486 //fprintf(stderr, "Cool! can switch banks\n");
4487 cur_bank = REG_BANK(reg);
4489 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4490 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4491 pCodeInsertAfter(pc->prev, new_pc);
4492 if(PCI(pc)->label) {
4493 PCI(new_pc)->label = PCI(pc)->label;
4494 PCI(pc)->label = NULL;
4497 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4498 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4499 pCodeInsertAfter(pc, new_pc);
4505 //fprintf(stderr, "Bummer can't switch banks\n");
4513 // } while(pc && !(isPCFL(pc)));
4518 if(pcprev && cur_bank) {
4519 /* Brute force - make sure that we point to bank 0 at the
4520 * end of each flow block */
4521 new_pc = newpCode(POC_BCF,
4522 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4523 pCodeInsertAfter(pcprev, new_pc);
4529 void pBlockDestruct(pBlock *pb)
4540 /*-----------------------------------------------------------------*/
4541 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4542 /* name dbName and combine them */
4543 /* into one block */
4544 /*-----------------------------------------------------------------*/
4545 void mergepBlocks(char dbName)
4548 pBlock *pb, *pbmerged = NULL,*pbn;
4550 pb = the_pFile->pbHead;
4552 //fprintf(stderr," merging blocks named %c\n",dbName);
4556 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4557 if( getpBlock_dbName(pb) == dbName) {
4559 //fprintf(stderr," merged block %c\n",dbName);
4564 addpCode2pBlock(pbmerged, pb->pcHead);
4565 /* addpCode2pBlock doesn't handle the tail: */
4566 pbmerged->pcTail = pb->pcTail;
4568 pb->prev->next = pbn;
4570 pbn->prev = pb->prev;
4575 //printpBlock(stderr, pbmerged);
4582 /*-----------------------------------------------------------------*/
4583 /* AnalyzeFlow - Examine the flow of the code and optimize */
4585 /* level 0 == minimal optimization */
4586 /* optimize registers that are used only by two instructions */
4587 /* level 1 == maximal optimization */
4588 /* optimize by looking at pairs of instructions that use the */
4590 /*-----------------------------------------------------------------*/
4592 void AnalyzeFlow(int level)
4594 static int times_called=0;
4602 /* if this is not the first time this function has been called,
4603 then clean up old flow information */
4604 if(times_called++) {
4605 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4608 RegsUnMapLiveRanges();
4614 /* Phase 2 - Flow Analysis - Register Banking
4616 * In this phase, the individual flow blocks are examined
4617 * and register banking is fixed.
4620 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4621 //FixRegisterBanking(pb);
4623 /* Phase 2 - Flow Analysis
4625 * In this phase, the pCode is partition into pCodeFlow
4626 * blocks. The flow blocks mark the points where a continuous
4627 * stream of instructions changes flow (e.g. because of
4628 * a call or goto or whatever).
4631 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4635 /* Phase 2 - Flow Analysis - linking flow blocks
4637 * In this phase, the individual flow blocks are examined
4638 * to determine their order of excution.
4641 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4644 /* Phase 3 - Flow Analysis - Flow Tree
4646 * In this phase, the individual flow blocks are examined
4647 * to determine their order of excution.
4650 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4654 /* Phase x - Flow Analysis - Used Banks
4656 * In this phase, the individual flow blocks are examined
4657 * to determine the Register Banks they use
4660 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4664 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4665 pCodeRegMapLiveRanges(pb);
4667 RemoveUnusedRegisters();
4669 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4670 pCodeRegOptimizeRegUsage(level);
4676 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4680 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4682 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4683 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4684 pcflow = pcflow->next) {
4686 FillFlow(PCFL(pcflow));
4691 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4693 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4694 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4695 pcflow = pcflow->next) {
4697 FlowStats(PCFL(pcflow));
4703 /*-----------------------------------------------------------------*/
4704 /* AnalyzeBanking - Called after the memory addresses have been */
4705 /* assigned to the registers. */
4707 /*-----------------------------------------------------------------*/
4709 void AnalyzeBanking(void)
4713 if(!picIsInitialized()) {
4714 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4715 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4716 fprintf(stderr,"support/scripts/inc2h.pl\n");
4717 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4722 /* Phase x - Flow Analysis - Used Banks
4724 * In this phase, the individual flow blocks are examined
4725 * to determine the Register Banks they use
4731 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4733 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4734 FixRegisterBanking(pb);
4738 /*-----------------------------------------------------------------*/
4739 /* buildCallTree - look at the flow and extract all of the calls */
4741 /*-----------------------------------------------------------------*/
4742 set *register_usage(pBlock *pb);
4744 void buildCallTree(void )
4755 /* Now build the call tree.
4756 First we examine all of the pCodes for functions.
4757 Keep in mind that the function boundaries coincide
4758 with pBlock boundaries.
4760 The algorithm goes something like this:
4761 We have two nested loops. The outer loop iterates
4762 through all of the pBlocks/functions. The inner
4763 loop iterates through all of the pCodes for
4764 a given pBlock. When we begin iterating through
4765 a pBlock, the variable pc_fstart, pCode of the start
4766 of a function, is cleared. We then search for pCodes
4767 of type PC_FUNCTION. When one is encountered, we
4768 initialize pc_fstart to this and at the same time
4769 associate a new pBranch object that signifies a
4770 branch entry. If a return is found, then this signifies
4771 a function exit point. We'll link the pCodes of these
4772 returns to the matching pc_fstart.
4774 When we're done, a doubly linked list of pBranches
4775 will exist. The head of this list is stored in
4776 `the_pFile', which is the meta structure for all
4777 of the pCode. Look at the printCallTree function
4778 on how the pBranches are linked together.
4781 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4782 pCode *pc_fstart=NULL;
4783 for(pc = pb->pcHead; pc; pc = pc->next) {
4785 if (PCF(pc)->fname) {
4787 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4788 //fprintf(stderr," found main \n");
4789 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4793 pbr = Safe_calloc(1,sizeof(pBranch));
4794 pbr->pc = pc_fstart = pc;
4797 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4799 // Here's a better way of doing the same:
4800 addSet(&pb->function_entries, pc);
4803 // Found an exit point in a function, e.g. return
4804 // (Note, there may be more than one return per function)
4806 pBranchLink(PCF(pc_fstart), PCF(pc));
4808 addSet(&pb->function_exits, pc);
4810 } else if(isCALL(pc)) {
4811 addSet(&pb->function_calls,pc);
4816 /* Re-allocate the registers so that there are no collisions
4817 * between local variables when one function call another */
4820 // pic14_deallocateAllRegs();
4822 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4829 /*-----------------------------------------------------------------*/
4830 /* AnalyzepCode - parse the pCode that has been generated and form */
4831 /* all of the logical connections. */
4833 /* Essentially what's done here is that the pCode flow is */
4835 /*-----------------------------------------------------------------*/
4837 void AnalyzepCode(char dbName)
4848 /* Phase 1 - Register allocation and peep hole optimization
4850 * The first part of the analysis is to determine the registers
4851 * that are used in the pCode. Once that is done, the peep rules
4852 * are applied to the code. We continue to loop until no more
4853 * peep rule optimizations are found (or until we exceed the
4854 * MAX_PASSES threshold).
4856 * When done, the required registers will be determined.
4862 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4863 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4865 /* First, merge the labels with the instructions */
4866 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4867 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4869 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4870 //fprintf(stderr," analyze and merging block %c\n",dbName);
4871 pBlockMergeLabels(pb);
4874 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4878 changes = OptimizepCode(dbName);
4880 } while(changes && (i++ < MAX_PASSES));
4885 /*-----------------------------------------------------------------*/
4886 /* ispCodeFunction - returns true if *pc is the pCode of a */
4888 /*-----------------------------------------------------------------*/
4889 bool ispCodeFunction(pCode *pc)
4892 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4898 /*-----------------------------------------------------------------*/
4899 /* findFunction - Search for a function by name (given the name) */
4900 /* in the set of all functions that are in a pBlock */
4901 /* (note - I expect this to change because I'm planning to limit */
4902 /* pBlock's to just one function declaration */
4903 /*-----------------------------------------------------------------*/
4904 pCode *findFunction(char *fname)
4911 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4913 pc = setFirstItem(pb->function_entries);
4916 if((pc->type == PC_FUNCTION) &&
4918 (strcmp(fname, PCF(pc)->fname)==0))
4921 pc = setNextItem(pb->function_entries);
4929 void MarkUsedRegisters(set *regset)
4934 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4935 r2 = pic14_regWithIdx(r1->rIdx);
4941 void pBlockStats(FILE *of, pBlock *pb)
4947 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4949 // for now just print the first element of each set
4950 pc = setFirstItem(pb->function_entries);
4952 fprintf(of,";entry: ");
4955 pc = setFirstItem(pb->function_exits);
4957 fprintf(of,";has an exit\n");
4961 pc = setFirstItem(pb->function_calls);
4963 fprintf(of,";functions called:\n");
4966 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4967 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4969 pc = setNextItem(pb->function_calls);
4973 r = setFirstItem(pb->tregisters);
4975 int n = elementsInSet(pb->tregisters);
4977 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4980 fprintf(of,"; %s\n",r->name);
4981 r = setNextItem(pb->tregisters);
4986 /*-----------------------------------------------------------------*/
4987 /*-----------------------------------------------------------------*/
4989 static void sequencepCode(void)
4995 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4997 pb->seq = GpCodeSequenceNumber+1;
4999 for( pc = pb->pcHead; pc; pc = pc->next)
5000 pc->seq = ++GpCodeSequenceNumber;
5006 /*-----------------------------------------------------------------*/
5007 /*-----------------------------------------------------------------*/
5008 set *register_usage(pBlock *pb)
5011 set *registers=NULL;
5012 set *registersInCallPath = NULL;
5014 /* check recursion */
5016 pc = setFirstItem(pb->function_entries);
5023 if(pc->type != PC_FUNCTION)
5024 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5026 pc = setFirstItem(pb->function_calls);
5027 for( ; pc; pc = setNextItem(pb->function_calls)) {
5029 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5030 char *dest = get_op_from_instruction(PCI(pc));
5032 pcn = findFunction(dest);
5034 registersInCallPath = register_usage(pcn->pb);
5036 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5041 pBlockStats(stderr,pb); // debug
5044 // Mark the registers in this block as used.
5046 MarkUsedRegisters(pb->tregisters);
5047 if(registersInCallPath) {
5048 /* registers were used in the functions this pBlock has called */
5049 /* so now, we need to see if these collide with the ones we are */
5052 regs *r1,*r2, *newreg;
5054 DFPRINTF((stderr,"comparing registers\n"));
5056 r1 = setFirstItem(registersInCallPath);
5059 r2 = setFirstItem(pb->tregisters);
5061 while(r2 && (r1->type != REG_STK)) {
5063 if(r2->rIdx == r1->rIdx) {
5064 newreg = pic14_findFreeReg(REG_GPR);
5068 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5072 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5073 r1->rIdx, newreg->rIdx));
5074 r2->rIdx = newreg->rIdx;
5075 //if(r2->name) free(r2->name);
5077 r2->name = Safe_strdup(newreg->name);
5081 newreg->wasUsed = 1;
5083 r2 = setNextItem(pb->tregisters);
5086 r1 = setNextItem(registersInCallPath);
5089 /* Collisions have been resolved. Now free the registers in the call path */
5090 r1 = setFirstItem(registersInCallPath);
5092 if(r1->type != REG_STK) {
5093 newreg = pic14_regWithIdx(r1->rIdx);
5096 r1 = setNextItem(registersInCallPath);
5100 // MarkUsedRegisters(pb->registers);
5102 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5105 DFPRINTF((stderr,"returning regs\n"));
5107 DFPRINTF((stderr,"not returning regs\n"));
5109 DFPRINTF((stderr,"pBlock after register optim.\n"));
5110 pBlockStats(stderr,pb); // debug
5116 /*-----------------------------------------------------------------*/
5117 /* printCallTree - writes the call tree to a file */
5119 /*-----------------------------------------------------------------*/
5120 void pct2(FILE *of,pBlock *pb,int indent)
5124 // set *registersInCallPath = NULL;
5130 return; //recursion ?
5132 pc = setFirstItem(pb->function_entries);
5139 for(i=0;i<indent;i++) // Indentation
5142 if(pc->type == PC_FUNCTION)
5143 fprintf(of,"%s\n",PCF(pc)->fname);
5148 pc = setFirstItem(pb->function_calls);
5149 for( ; pc; pc = setNextItem(pb->function_calls)) {
5151 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5152 char *dest = get_op_from_instruction(PCI(pc));
5154 pcn = findFunction(dest);
5156 pct2(of,pcn->pb,indent+1);
5158 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5166 /*-----------------------------------------------------------------*/
5167 /* printCallTree - writes the call tree to a file */
5169 /*-----------------------------------------------------------------*/
5171 void printCallTree(FILE *of)
5183 fprintf(of, "\npBlock statistics\n");
5184 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5189 fprintf(of,"Call Tree\n");
5190 pbr = the_pFile->functions;
5194 if(!ispCodeFunction(pc))
5195 fprintf(of,"bug in call tree");
5198 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5200 while(pc->next && !ispCodeFunction(pc->next)) {
5202 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5203 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5211 fprintf(of,"\n**************\n\na better call tree\n");
5212 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5217 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5218 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5224 /*-----------------------------------------------------------------*/
5226 /*-----------------------------------------------------------------*/
5228 void InlineFunction(pBlock *pb)
5236 pc = setFirstItem(pb->function_calls);
5238 for( ; pc; pc = setNextItem(pb->function_calls)) {
5241 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5247 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5249 //fprintf(stderr,"Cool can inline:\n");
5250 //pcn->print(stderr,pcn);
5252 //fprintf(stderr,"recursive call Inline\n");
5253 InlineFunction(pcn->pb);
5254 //fprintf(stderr,"return from recursive call Inline\n");
5257 At this point, *pc points to a CALL mnemonic, and
5258 *pcn points to the function that is being called.
5260 To in-line this call, we need to remove the CALL
5261 and RETURN(s), and link the function pCode in with
5267 /* Remove the CALL */
5271 /* remove callee pBlock from the pBlock linked list */
5272 removepBlock(pcn->pb);
5280 /* Remove the Function pCode */
5281 pct = findNextInstruction(pcn->next);
5283 /* Link the function with the callee */
5284 pc->next = pcn->next;
5285 pcn->next->prev = pc;
5287 /* Convert the function name into a label */
5289 pbr = Safe_calloc(1,sizeof(pBranch));
5290 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5292 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5293 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5295 /* turn all of the return's except the last into goto's */
5296 /* check case for 2 instruction pBlocks */
5297 pce = findNextInstruction(pcn->next);
5299 pCode *pce_next = findNextInstruction(pce->next);
5301 if(pce_next == NULL) {
5302 /* found the last return */
5303 pCode *pc_call_next = findNextInstruction(pc_call->next);
5305 //fprintf(stderr,"found last return\n");
5306 //pce->print(stderr,pce);
5307 pce->prev->next = pc_call->next;
5308 pc_call->next->prev = pce->prev;
5309 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5319 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5325 /*-----------------------------------------------------------------*/
5327 /*-----------------------------------------------------------------*/
5329 void InlinepCode(void)
5338 if(!functionInlining)
5341 /* Loop through all of the function definitions and count the
5342 * number of times each one is called */
5343 //fprintf(stderr,"inlining %d\n",__LINE__);
5345 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5347 pc = setFirstItem(pb->function_calls);
5349 for( ; pc; pc = setNextItem(pb->function_calls)) {
5352 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5353 if(pcn && isPCF(pcn)) {
5354 PCF(pcn)->ncalled++;
5357 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5362 //fprintf(stderr,"inlining %d\n",__LINE__);
5364 /* Now, Loop through the function definitions again, but this
5365 * time inline those functions that have only been called once. */
5367 InlineFunction(the_pFile->pbHead);
5368 //fprintf(stderr,"inlining %d\n",__LINE__);
5370 for(pb = the_pFile->pbHead; pb; pb = pb->next)