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 pciCLRWDT = {
439 {PC_OPCODE, NULL, NULL, 0, NULL,
452 0,0, // dest, bit instruction
459 pCodeInstruction pciDECF = {
460 {PC_OPCODE, NULL, NULL, 0, NULL,
473 1,0, // dest, bit instruction
476 PCC_REGISTER, // inCond
477 PCC_REGISTER // outCond
480 pCodeInstruction pciDECFW = {
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 0,0, // dest, bit instruction
497 PCC_REGISTER, // inCond
501 pCodeInstruction pciDECFSZ = {
502 {PC_OPCODE, NULL, NULL, 0, NULL,
515 1,0, // dest, bit instruction
518 PCC_REGISTER, // inCond
519 PCC_REGISTER // outCond
522 pCodeInstruction pciDECFSZW = {
523 {PC_OPCODE, NULL, NULL, 0, NULL,
536 0,0, // dest, bit instruction
539 PCC_REGISTER, // inCond
543 pCodeInstruction pciGOTO = {
544 {PC_OPCODE, NULL, NULL, 0, NULL,
557 0,0, // dest, bit instruction
564 pCodeInstruction pciINCF = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 1,0, // dest, bit instruction
581 PCC_REGISTER, // inCond
582 PCC_REGISTER // outCond
585 pCodeInstruction pciINCFW = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 0,0, // dest, bit instruction
602 PCC_REGISTER, // inCond
606 pCodeInstruction pciINCFSZ = {
607 {PC_OPCODE, NULL, NULL, 0, NULL,
620 1,0, // dest, bit instruction
623 PCC_REGISTER, // inCond
624 PCC_REGISTER // outCond
627 pCodeInstruction pciINCFSZW = {
628 {PC_OPCODE, NULL, NULL, 0, NULL,
641 0,0, // dest, bit instruction
644 PCC_REGISTER, // inCond
648 pCodeInstruction pciIORWF = {
649 {PC_OPCODE, NULL, NULL, 0, NULL,
662 1,0, // dest, bit instruction
665 (PCC_W | PCC_REGISTER), // inCond
666 (PCC_REGISTER | PCC_Z) // outCond
669 pCodeInstruction pciIORFW = {
670 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,0, // dest, bit instruction
686 (PCC_W | PCC_REGISTER), // inCond
687 (PCC_W | PCC_Z) // outCond
690 pCodeInstruction pciIORLW = {
691 {PC_OPCODE, NULL, NULL, 0, NULL,
704 0,0, // dest, bit instruction
707 (PCC_W | PCC_LITERAL), // inCond
708 (PCC_W | PCC_Z) // outCond
711 pCodeInstruction pciMOVF = {
712 {PC_OPCODE, NULL, NULL, 0, NULL,
725 1,0, // dest, bit instruction
728 PCC_REGISTER, // inCond
732 pCodeInstruction pciMOVFW = {
733 {PC_OPCODE, NULL, NULL, 0, NULL,
746 0,0, // dest, bit instruction
749 PCC_REGISTER, // inCond
750 (PCC_W | PCC_Z) // outCond
753 pCodeInstruction pciMOVWF = {
754 {PC_OPCODE, NULL, NULL, 0, NULL,
767 0,0, // dest, bit instruction
771 PCC_REGISTER // outCond
774 pCodeInstruction pciMOVLW = {
775 {PC_OPCODE, NULL, NULL, 0, NULL,
788 0,0, // dest, bit instruction
791 (PCC_NONE | PCC_LITERAL), // inCond
795 pCodeInstruction pciNOP = {
796 {PC_OPCODE, NULL, NULL, 0, NULL,
808 0,0, // dest, bit instruction
815 pCodeInstruction pciRETFIE = {
816 {PC_OPCODE, NULL, NULL, 0, NULL,
829 0,0, // dest, bit instruction
833 PCC_NONE // outCond (not true... affects the GIE bit too)
836 pCodeInstruction pciRETLW = {
837 {PC_OPCODE, NULL, NULL, 0, NULL,
850 0,0, // dest, bit instruction
853 PCC_LITERAL, // inCond
857 pCodeInstruction pciRETURN = {
858 {PC_OPCODE, NULL, NULL, 0, NULL,
871 0,0, // dest, bit instruction
878 pCodeInstruction pciRLF = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 1,0, // dest, bit instruction
895 (PCC_C | PCC_REGISTER), // inCond
896 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
899 pCodeInstruction pciRLFW = {
900 {PC_OPCODE, NULL, NULL, 0, NULL,
913 0,0, // dest, bit instruction
916 (PCC_C | PCC_REGISTER), // inCond
917 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
920 pCodeInstruction pciRRF = {
921 {PC_OPCODE, NULL, NULL, 0, NULL,
934 1,0, // dest, bit instruction
937 (PCC_C | PCC_REGISTER), // inCond
938 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
941 pCodeInstruction pciRRFW = {
942 {PC_OPCODE, NULL, NULL, 0, NULL,
955 0,0, // dest, bit instruction
958 (PCC_C | PCC_REGISTER), // inCond
959 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
962 pCodeInstruction pciSUBWF = {
963 {PC_OPCODE, NULL, NULL, 0, NULL,
976 1,0, // dest, bit instruction
979 (PCC_W | PCC_REGISTER), // inCond
980 (PCC_REGISTER | PCC_Z) // outCond
983 pCodeInstruction pciSUBFW = {
984 {PC_OPCODE, NULL, NULL, 0, NULL,
997 0,0, // dest, bit instruction
1000 (PCC_W | PCC_REGISTER), // inCond
1001 (PCC_W | PCC_Z) // outCond
1004 pCodeInstruction pciSUBLW = {
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 0,0, // dest, bit instruction
1019 0,0, // branch, skip
1021 (PCC_W | PCC_LITERAL), // inCond
1022 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1025 pCodeInstruction pciSWAPF = {
1026 {PC_OPCODE, NULL, NULL, 0, NULL,
1032 NULL, // from branch
1039 1,0, // dest, bit instruction
1040 0,0, // branch, skip
1042 (PCC_REGISTER), // inCond
1043 (PCC_REGISTER) // outCond
1046 pCodeInstruction pciSWAPFW = {
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 0,0, // branch, skip
1063 (PCC_REGISTER), // inCond
1067 pCodeInstruction pciTRIS = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 0,0, // dest, bit instruction
1082 0,0, // branch, skip
1085 PCC_REGISTER // outCond
1088 pCodeInstruction pciXORWF = {
1089 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 1,0, // dest, bit instruction
1103 0,0, // branch, skip
1105 (PCC_W | PCC_REGISTER), // inCond
1106 (PCC_REGISTER | PCC_Z) // outCond
1109 pCodeInstruction pciXORFW = {
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_REGISTER), // inCond
1127 (PCC_W | PCC_Z) // outCond
1130 pCodeInstruction pciXORLW = {
1131 {PC_OPCODE, NULL, NULL, 0, NULL,
1137 NULL, // from branch
1144 0,0, // dest, bit instruction
1145 0,0, // branch, skip
1147 (PCC_W | PCC_LITERAL), // inCond
1148 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1152 #define MAX_PIC14MNEMONICS 100
1153 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1155 /* This definition needs to be part of configure.in */
1156 // #define USE_VSNPRINTF
1158 #ifdef USE_VSNPRINTF
1159 // Alas, vsnprintf is not ANSI standard, and does not exist
1160 // on Solaris (and probably other non-Gnu flavored Unixes).
1162 /*-----------------------------------------------------------------*/
1163 /* SAFE_snprintf - like snprintf except the string pointer is */
1164 /* after the string has been printed to. This is */
1165 /* useful for printing to string as though if it */
1166 /* were a stream. */
1167 /*-----------------------------------------------------------------*/
1168 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1176 va_start(val, format);
1178 vsnprintf(*str, *size, format, val);
1184 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1185 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1193 #else // USE_VSNPRINTF
1195 // This version is *not* safe, despite the name.
1197 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1201 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1206 va_start(val, format);
1208 vsprintf(buffer, format, val);
1211 len = strlen(buffer);
1213 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1214 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1217 strcpy(*str, buffer);
1223 #endif // USE_VSNPRINTF
1226 extern void initStack(int base_address, int size);
1227 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1228 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1229 extern void init_pic(char *);
1231 void pCodeInitRegisters(void)
1233 static int initialized=0;
1239 initStack(0xfff, 8);
1240 init_pic(port->processor);
1242 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1243 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1244 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1245 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1246 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1247 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1249 pc_status.rIdx = IDX_STATUS;
1250 pc_fsr.rIdx = IDX_FSR;
1251 pc_indf.rIdx = IDX_INDF;
1252 pc_intcon.rIdx = IDX_INTCON;
1253 pc_pcl.rIdx = IDX_PCL;
1254 pc_pclath.rIdx = IDX_PCLATH;
1256 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1257 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1258 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1260 pc_kzero.rIdx = IDX_KZ;
1261 pc_wsave.rIdx = IDX_WSAVE;
1262 pc_ssave.rIdx = IDX_SSAVE;
1264 /* probably should put this in a separate initialization routine */
1265 pb_dead_pcodes = newpBlock();
1269 /*-----------------------------------------------------------------*/
1270 /* mnem2key - convert a pic mnemonic into a hash key */
1271 /* (BTW - this spreads the mnemonics quite well) */
1273 /*-----------------------------------------------------------------*/
1275 int mnem2key(char const *mnem)
1284 key += toupper(*mnem++) +1;
1288 return (key & 0x1f);
1292 void pic14initMnemonics(void)
1297 pCodeInstruction *pci;
1299 if(mnemonics_initialized)
1302 //FIXME - probably should NULL out the array before making the assignments
1303 //since we check the array contents below this initialization.
1305 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1306 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1307 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1308 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1309 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1310 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1311 pic14Mnemonics[POC_BCF] = &pciBCF;
1312 pic14Mnemonics[POC_BSF] = &pciBSF;
1313 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1314 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1315 pic14Mnemonics[POC_CALL] = &pciCALL;
1316 pic14Mnemonics[POC_COMF] = &pciCOMF;
1317 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1318 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1319 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1320 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1321 pic14Mnemonics[POC_DECF] = &pciDECF;
1322 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1323 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1324 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1325 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1326 pic14Mnemonics[POC_INCF] = &pciINCF;
1327 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1328 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1329 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1330 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1331 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1332 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1333 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1334 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1335 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1336 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1337 pic14Mnemonics[POC_NOP] = &pciNOP;
1338 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1339 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1340 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1341 pic14Mnemonics[POC_RLF] = &pciRLF;
1342 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1343 pic14Mnemonics[POC_RRF] = &pciRRF;
1344 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1345 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1346 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1347 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1348 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1349 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1350 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1351 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1352 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1353 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1355 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1356 if(pic14Mnemonics[i])
1357 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1358 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1361 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1362 pci = hTabNextItem(pic14MnemonicsHash, &key);
1365 mnemonics_initialized = 1;
1368 int getpCodePeepCommand(char *cmd);
1370 int getpCode(char *mnem,unsigned dest)
1373 pCodeInstruction *pci;
1374 int key = mnem2key(mnem);
1376 if(!mnemonics_initialized)
1377 pic14initMnemonics();
1379 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1383 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1384 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1388 pci = hTabNextItemWK (pic14MnemonicsHash);
1395 /*-----------------------------------------------------------------*
1396 * pic14initpCodePeepCommands
1398 *-----------------------------------------------------------------*/
1399 void pic14initpCodePeepCommands(void)
1407 hTabAddItem(&pic14pCodePeepCommandsHash,
1408 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1410 } while (peepCommands[i].cmd);
1412 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1415 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1416 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1421 /*-----------------------------------------------------------------
1424 *-----------------------------------------------------------------*/
1426 int getpCodePeepCommand(char *cmd)
1430 int key = mnem2key(cmd);
1433 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1436 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1437 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1441 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1448 char getpBlock_dbName(pBlock *pb)
1454 return pb->cmemmap->dbName;
1458 void pBlockConvert2ISR(pBlock *pb)
1469 /*-----------------------------------------------------------------*/
1470 /* movepBlock2Head - given the dbname of a pBlock, move all */
1471 /* instances to the front of the doubly linked */
1472 /* list of pBlocks */
1473 /*-----------------------------------------------------------------*/
1475 void movepBlock2Head(char dbName)
1479 pb = the_pFile->pbHead;
1483 if(getpBlock_dbName(pb) == dbName) {
1484 pBlock *pbn = pb->next;
1485 pb->next = the_pFile->pbHead;
1486 the_pFile->pbHead->prev = pb;
1487 the_pFile->pbHead = pb;
1490 pb->prev->next = pbn;
1492 // If the pBlock that we just moved was the last
1493 // one in the link of all of the pBlocks, then we
1494 // need to point the tail to the block just before
1495 // the one we moved.
1496 // Note: if pb->next is NULL, then pb must have
1497 // been the last pBlock in the chain.
1500 pbn->prev = pb->prev;
1502 the_pFile->pbTail = pb->prev;
1513 void copypCode(FILE *of, char dbName)
1517 if(!of || !the_pFile)
1520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1521 if(getpBlock_dbName(pb) == dbName) {
1528 void pcode_test(void)
1531 DFPRINTF((stderr,"pcode is alive!\n"));
1541 /* create the file name */
1542 strcpy(buffer,srcFileName);
1543 strcat(buffer,".p");
1545 if( !(pFile = fopen(buffer, "w" ))) {
1546 werror(E_FILE_OPEN_ERR,buffer);
1550 fprintf(pFile,"pcode dump\n\n");
1552 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1553 fprintf(pFile,"\n\tNew pBlock\n\n");
1555 fprintf(pFile,"%s",pb->cmemmap->sname);
1557 fprintf(pFile,"internal pblock");
1559 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1560 printpBlock(pFile,pb);
1564 /*-----------------------------------------------------------------*/
1565 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1566 /* ister, RegCond will return the bit being referenced. */
1568 /* fixme - why not just OR in the pcop bit field */
1569 /*-----------------------------------------------------------------*/
1571 static int RegCond(pCodeOp *pcop)
1577 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1578 switch(PCORB(pcop)->bit) {
1592 /*-----------------------------------------------------------------*/
1593 /* newpCode - create and return a newly initialized pCode */
1595 /* fixme - rename this */
1597 /* The purpose of this routine is to create a new Instruction */
1598 /* pCode. This is called by gen.c while the assembly code is being */
1602 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1603 /* (note that the op is analogous to but not the */
1604 /* same thing as the opcode of the instruction.) */
1605 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1608 /* a pointer to the new malloc'd pCode is returned. */
1612 /*-----------------------------------------------------------------*/
1613 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1615 pCodeInstruction *pci ;
1617 if(!mnemonics_initialized)
1618 pic14initMnemonics();
1620 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1622 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1623 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1626 if(pci->inCond & PCC_EXAMINE_PCOP)
1627 pci->inCond |= RegCond(pcop);
1629 if(pci->outCond & PCC_EXAMINE_PCOP)
1630 pci->outCond |= RegCond(pcop);
1632 pci->pc.prev = pci->pc.next = NULL;
1633 return (pCode *)pci;
1636 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1642 /*-----------------------------------------------------------------*/
1643 /* newpCodeWild - create a "wild" as in wild card pCode */
1645 /* Wild pcodes are used during the peep hole optimizer to serve */
1646 /* as place holders for any instruction. When a snippet of code is */
1647 /* compared to a peep hole rule, the wild card opcode will match */
1648 /* any instruction. However, the optional operand and label are */
1649 /* additional qualifiers that must also be matched before the */
1650 /* line (of assembly code) is declared matched. Note that the */
1651 /* operand may be wild too. */
1653 /* Note, a wild instruction is specified just like a wild var: */
1654 /* %4 ; A wild instruction, */
1655 /* See the peeph.def file for additional examples */
1657 /*-----------------------------------------------------------------*/
1659 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1664 pcw = Safe_calloc(1,sizeof(pCodeWild));
1666 pcw->pci.pc.type = PC_WILD;
1667 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1668 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1669 pcw->pci.pc.pb = NULL;
1671 // pcw->pci.pc.analyze = genericAnalyze;
1672 pcw->pci.pc.destruct = genericDestruct;
1673 pcw->pci.pc.print = genericPrint;
1675 pcw->id = pCodeID; // this is the 'n' in %n
1676 pcw->operand = optional_operand;
1677 pcw->label = optional_label;
1679 pcw->mustBeBitSkipInst = 0;
1680 pcw->mustNotBeBitSkipInst = 0;
1681 pcw->invertBitSkipInst = 0;
1683 return ( (pCode *)pcw);
1687 /*-----------------------------------------------------------------*/
1688 /* newPcodeInlineP - create a new pCode from a char string */
1689 /*-----------------------------------------------------------------*/
1692 pCode *newpCodeInlineP(char *cP)
1697 pcc = Safe_calloc(1,sizeof(pCodeComment));
1699 pcc->pc.type = PC_INLINE;
1700 pcc->pc.prev = pcc->pc.next = NULL;
1701 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1704 // pcc->pc.analyze = genericAnalyze;
1705 pcc->pc.destruct = genericDestruct;
1706 pcc->pc.print = genericPrint;
1709 pcc->comment = Safe_strdup(cP);
1711 pcc->comment = NULL;
1713 return ( (pCode *)pcc);
1717 /*-----------------------------------------------------------------*/
1718 /* newPcodeCharP - create a new pCode from a char string */
1719 /*-----------------------------------------------------------------*/
1721 pCode *newpCodeCharP(char *cP)
1726 pcc = Safe_calloc(1,sizeof(pCodeComment));
1728 pcc->pc.type = PC_COMMENT;
1729 pcc->pc.prev = pcc->pc.next = NULL;
1730 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1733 // pcc->pc.analyze = genericAnalyze;
1734 pcc->pc.destruct = genericDestruct;
1735 pcc->pc.print = genericPrint;
1738 pcc->comment = Safe_strdup(cP);
1740 pcc->comment = NULL;
1742 return ( (pCode *)pcc);
1746 /*-----------------------------------------------------------------*/
1747 /* newpCodeFunction - */
1748 /*-----------------------------------------------------------------*/
1751 pCode *newpCodeFunction(char *mod,char *f)
1755 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1756 //_ALLOC(pcf,sizeof(pCodeFunction));
1758 pcf->pc.type = PC_FUNCTION;
1759 pcf->pc.prev = pcf->pc.next = NULL;
1760 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1763 // pcf->pc.analyze = genericAnalyze;
1764 pcf->pc.destruct = genericDestruct;
1765 pcf->pc.print = pCodePrintFunction;
1770 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1771 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1772 strcpy(pcf->modname,mod);
1774 pcf->modname = NULL;
1777 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1778 pcf->fname = Safe_calloc(1,strlen(f)+1);
1779 strcpy(pcf->fname,f);
1783 return ( (pCode *)pcf);
1787 /*-----------------------------------------------------------------*/
1789 /*-----------------------------------------------------------------*/
1790 void destructpCodeFlow(pCode *pc)
1792 if(!pc || !isPCFL(pc))
1801 deleteSet(&PCFL(pc)->registers);
1802 deleteSet(&PCFL(pc)->from);
1803 deleteSet(&PCFL(pc)->to);
1808 pCode *newpCodeFlow(void )
1812 //_ALLOC(pcflow,sizeof(pCodeFlow));
1813 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1815 pcflow->pc.type = PC_FLOW;
1816 pcflow->pc.prev = pcflow->pc.next = NULL;
1817 pcflow->pc.pb = NULL;
1819 // pcflow->pc.analyze = genericAnalyze;
1820 pcflow->pc.destruct = destructpCodeFlow;
1821 pcflow->pc.print = genericPrint;
1823 pcflow->pc.seq = GpcFlowSeq++;
1825 pcflow->from = pcflow->to = NULL;
1827 pcflow->inCond = PCC_NONE;
1828 pcflow->outCond = PCC_NONE;
1830 pcflow->firstBank = -1;
1831 pcflow->lastBank = -1;
1833 pcflow->FromConflicts = 0;
1834 pcflow->ToConflicts = 0;
1838 pcflow->registers = newSet();
1840 return ( (pCode *)pcflow);
1844 /*-----------------------------------------------------------------*/
1845 /*-----------------------------------------------------------------*/
1846 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1848 pCodeFlowLink *pcflowLink;
1850 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1852 pcflowLink->pcflow = pcflow;
1853 pcflowLink->bank_conflict = 0;
1858 /*-----------------------------------------------------------------*/
1859 /* newpCodeCSource - create a new pCode Source Symbol */
1860 /*-----------------------------------------------------------------*/
1862 pCode *newpCodeCSource(int ln, char *f, char *l)
1867 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1869 pccs->pc.type = PC_CSOURCE;
1870 pccs->pc.prev = pccs->pc.next = NULL;
1873 pccs->pc.destruct = genericDestruct;
1874 pccs->pc.print = genericPrint;
1876 pccs->line_number = ln;
1878 pccs->line = Safe_strdup(l);
1883 pccs->file_name = Safe_strdup(f);
1885 pccs->file_name = NULL;
1887 return ( (pCode *)pccs);
1890 /*-----------------------------------------------------------------*/
1891 /* pCodeLabelDestruct - free memory used by a label. */
1892 /*-----------------------------------------------------------------*/
1893 static void pCodeLabelDestruct(pCode *pc)
1899 if((pc->type == PC_LABEL) && PCL(pc)->label)
1900 free(PCL(pc)->label);
1906 pCode *newpCodeLabel(char *name, int key)
1912 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1914 pcl->pc.type = PC_LABEL;
1915 pcl->pc.prev = pcl->pc.next = NULL;
1916 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1919 // pcl->pc.analyze = genericAnalyze;
1920 pcl->pc.destruct = pCodeLabelDestruct;
1921 pcl->pc.print = pCodePrintLabel;
1927 sprintf(s,"_%05d_DS_",key);
1932 pcl->label = Safe_strdup(s);
1935 return ( (pCode *)pcl);
1940 /*-----------------------------------------------------------------*/
1941 /* newpBlock - create and return a pointer to a new pBlock */
1942 /*-----------------------------------------------------------------*/
1943 pBlock *newpBlock(void)
1948 PpB = Safe_calloc(1,sizeof(pBlock) );
1949 PpB->next = PpB->prev = NULL;
1951 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1952 PpB->tregisters = NULL;
1954 PpB->FlowTree = NULL;
1960 /*-----------------------------------------------------------------*/
1961 /* newpCodeChain - create a new chain of pCodes */
1962 /*-----------------------------------------------------------------*
1964 * This function will create a new pBlock and the pointer to the
1965 * pCode that is passed in will be the first pCode in the block.
1966 *-----------------------------------------------------------------*/
1969 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1972 pBlock *pB = newpBlock();
1974 pB->pcHead = pB->pcTail = pc;
1981 /*-----------------------------------------------------------------*/
1982 /* newpCodeOpLabel - Create a new label given the key */
1983 /* Note, a negative key means that the label is part of wild card */
1984 /* (and hence a wild card label) used in the pCodePeep */
1985 /* optimizations). */
1986 /*-----------------------------------------------------------------*/
1988 pCodeOp *newpCodeOpLabel(char *name, int key)
1991 static int label_key=-1;
1995 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1996 pcop->type = PO_LABEL;
2001 sprintf(s=buffer,"_%05d_DS_",key);
2003 s = name, key = label_key--;
2006 pcop->name = Safe_strdup(s);
2008 ((pCodeOpLabel *)pcop)->key = key;
2013 /*-----------------------------------------------------------------*/
2014 /*-----------------------------------------------------------------*/
2015 pCodeOp *newpCodeOpLit(int lit)
2021 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2022 pcop->type = PO_LITERAL;
2026 sprintf(s,"0x%02x",lit);
2028 pcop->name = Safe_strdup(s);
2031 ((pCodeOpLit *)pcop)->lit = lit;
2036 /*-----------------------------------------------------------------*/
2037 /*-----------------------------------------------------------------*/
2038 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2042 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2043 pcop->type = PO_IMMEDIATE;
2045 regs *r = dirregWithName(name);
2046 pcop->name = Safe_strdup(name);
2049 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2050 PCOI(pcop)->rIdx = r->rIdx;
2052 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2053 PCOI(pcop)->rIdx = -1;
2055 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2060 PCOI(pcop)->index = index;
2061 PCOI(pcop)->offset = offset;
2062 PCOI(pcop)->_const = code_space;
2067 /*-----------------------------------------------------------------*/
2068 /*-----------------------------------------------------------------*/
2069 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2075 if(!pcwb || !subtype) {
2076 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2080 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2081 pcop->type = PO_WILD;
2082 sprintf(s,"%%%d",id);
2083 pcop->name = Safe_strdup(s);
2085 PCOW(pcop)->id = id;
2086 PCOW(pcop)->pcwb = pcwb;
2087 PCOW(pcop)->subtype = subtype;
2088 PCOW(pcop)->matched = NULL;
2093 /*-----------------------------------------------------------------*/
2094 /*-----------------------------------------------------------------*/
2095 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2099 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2100 pcop->type = PO_GPR_BIT;
2102 pcop->name = Safe_strdup(s);
2106 PCORB(pcop)->bit = bit;
2107 PCORB(pcop)->inBitSpace = inBitSpace;
2112 /*-----------------------------------------------------------------*
2113 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2115 * If rIdx >=0 then a specific register from the set of registers
2116 * will be selected. If rIdx <0, then a new register will be searched
2118 *-----------------------------------------------------------------*/
2120 pCodeOp *newpCodeOpReg(int rIdx)
2124 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2129 PCOR(pcop)->rIdx = rIdx;
2130 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2132 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2135 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2136 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2139 pcop->type = PCOR(pcop)->r->pc_type;
2144 pCodeOp *newpCodeOpRegFromStr(char *name)
2148 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2149 PCOR(pcop)->r = allocRegByName(name, 1);
2150 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2151 pcop->type = PCOR(pcop)->r->pc_type;
2152 pcop->name = PCOR(pcop)->r->name;
2157 /*-----------------------------------------------------------------*/
2158 /*-----------------------------------------------------------------*/
2160 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2167 pcop = newpCodeOpBit(name, -1,0);
2171 pcop = newpCodeOpLit(-1);
2175 pcop = newpCodeOpLabel(NULL,-1);
2178 pcop = newpCodeOpReg(-1);
2182 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2185 pcop->name = Safe_strdup(name);
2193 /*-----------------------------------------------------------------*/
2194 /*-----------------------------------------------------------------*/
2195 void pCodeConstString(char *name, char *value)
2199 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2204 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2208 sprintf(buffer,"; %s = %s",name,value);
2210 addpCode2pBlock(pb,newpCodeCharP(buffer));
2211 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2214 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2220 /*-----------------------------------------------------------------*/
2221 /*-----------------------------------------------------------------*/
2222 void pCodeReadCodeTable(void)
2226 fprintf(stderr, " %s\n",__FUNCTION__);
2228 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2232 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2233 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2234 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2235 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2237 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2238 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2239 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2240 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2245 /*-----------------------------------------------------------------*/
2246 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2247 /*-----------------------------------------------------------------*/
2248 void addpCode2pBlock(pBlock *pb, pCode *pc)
2255 /* If this is the first pcode to be added to a block that
2256 * was initialized with a NULL pcode, then go ahead and
2257 * make this pcode the head and tail */
2258 pb->pcHead = pb->pcTail = pc;
2261 pb->pcTail->next = pc;
2263 pc->prev = pb->pcTail;
2270 /*-----------------------------------------------------------------*/
2271 /* addpBlock - place a pBlock into the pFile */
2272 /*-----------------------------------------------------------------*/
2273 void addpBlock(pBlock *pb)
2275 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2278 /* First time called, we'll pass through here. */
2279 //_ALLOC(the_pFile,sizeof(pFile));
2280 the_pFile = Safe_calloc(1,sizeof(pFile));
2281 the_pFile->pbHead = the_pFile->pbTail = pb;
2282 the_pFile->functions = NULL;
2286 the_pFile->pbTail->next = pb;
2287 pb->prev = the_pFile->pbTail;
2289 the_pFile->pbTail = pb;
2292 /*-----------------------------------------------------------------*/
2293 /* removepBlock - remove a pBlock from the pFile */
2294 /*-----------------------------------------------------------------*/
2295 void removepBlock(pBlock *pb)
2303 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2305 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2308 if(pbs == the_pFile->pbHead)
2309 the_pFile->pbHead = pbs->next;
2311 if (pbs == the_pFile->pbTail)
2312 the_pFile->pbTail = pbs->prev;
2315 pbs->next->prev = pbs->prev;
2318 pbs->prev->next = pbs->next;
2325 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2329 /*-----------------------------------------------------------------*/
2330 /* printpCode - write the contents of a pCode to a file */
2331 /*-----------------------------------------------------------------*/
2332 void printpCode(FILE *of, pCode *pc)
2343 fprintf(of,"warning - unable to print pCode\n");
2346 /*-----------------------------------------------------------------*/
2347 /* printpBlock - write the contents of a pBlock to a file */
2348 /*-----------------------------------------------------------------*/
2349 void printpBlock(FILE *of, pBlock *pb)
2359 for(pc = pb->pcHead; pc; pc = pc->next)
2364 /*-----------------------------------------------------------------*/
2366 /* pCode processing */
2370 /*-----------------------------------------------------------------*/
2372 void unlinkpCode(pCode *pc)
2378 fprintf(stderr,"Unlinking: ");
2379 printpCode(stderr, pc);
2382 pc->prev->next = pc->next;
2384 pc->next->prev = pc->prev;
2386 pc->prev = pc->next = NULL;
2390 /*-----------------------------------------------------------------*/
2391 /*-----------------------------------------------------------------*/
2393 static void genericDestruct(pCode *pc)
2399 /* For instructions, tell the register (if there's one used)
2400 * that it's no longer needed */
2401 regs *reg = getRegFromInstruction(pc);
2403 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2406 /* Instead of deleting the memory used by this pCode, mark
2407 * the object as bad so that if there's a pointer to this pCode
2408 * dangling around somewhere then (hopefully) when the type is
2409 * checked we'll catch it.
2414 addpCode2pBlock(pb_dead_pcodes, pc);
2421 /*-----------------------------------------------------------------*/
2422 /*-----------------------------------------------------------------*/
2423 void pBlockRegs(FILE *of, pBlock *pb)
2428 r = setFirstItem(pb->tregisters);
2430 r = setNextItem(pb->tregisters);
2435 /*-----------------------------------------------------------------*/
2436 /*-----------------------------------------------------------------*/
2437 char *get_op(pCodeOp *pcop,char *buffer, int size)
2442 int use_buffer = 1; // copy the string to the passed buffer pointer
2447 use_buffer = 0; // Don't bother copying the string to the buffer.
2451 switch(pcop->type) {
2455 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2458 return PCOR(pcop)->r->name;
2461 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2464 SAFE_snprintf(&buffer,&size,"%s",r->name);
2474 if(PCOI(pcop)->_const) {
2476 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2477 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2480 8 * PCOI(pcop)->offset );
2482 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2485 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2486 SAFE_snprintf(&s,&size,"(%s + %d)",
2488 PCOI(pcop)->index );
2490 SAFE_snprintf(&s,&size,"%s",pcop->name);
2497 //size = sizeof(buffer);
2498 if( PCOR(pcop)->instance) {
2499 SAFE_snprintf(&s,&size,"(%s + %d)",
2501 PCOR(pcop)->instance );
2502 //fprintf(stderr,"PO_DIR %s\n",buffer);
2504 SAFE_snprintf(&s,&size,"%s",pcop->name);
2510 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2519 return "NO operand";
2523 /*-----------------------------------------------------------------*/
2524 /*-----------------------------------------------------------------*/
2525 static char *get_op_from_instruction( pCodeInstruction *pcc)
2529 return get_op(pcc->pcop,NULL,0);
2531 return ("ERROR Null: "__FUNCTION__);
2535 /*-----------------------------------------------------------------*/
2536 /*-----------------------------------------------------------------*/
2537 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2540 fprintf(of,"pcodeopprint- not implemented\n");
2543 /*-----------------------------------------------------------------*/
2544 /*-----------------------------------------------------------------*/
2545 char *pCode2str(char *str, int size, pCode *pc)
2553 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2555 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2557 if(PCI(pc)->isBitInst) {
2558 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2559 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2560 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2561 PCI(pc)->pcop->name ,
2562 PCI(pc)->pcop->name );
2564 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2565 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2566 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2567 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2569 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2570 //PCI(pc)->pcop->t.bit );
2573 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2574 if( PCI(pc)->num_ops == 2)
2575 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2577 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2580 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2582 if( PCI(pc)->num_ops == 2)
2583 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2591 /* assuming that comment ends with a \n */
2592 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2596 /* assuming that inline code ends with a \n */
2597 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2601 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2604 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2607 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2610 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2613 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2617 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2624 /*-----------------------------------------------------------------*/
2625 /* genericPrint - the contents of a pCode to a file */
2626 /*-----------------------------------------------------------------*/
2627 static void genericPrint(FILE *of, pCode *pc)
2635 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2639 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2643 // If the opcode has a label, print that first
2645 pBranch *pbl = PCI(pc)->label;
2646 while(pbl && pbl->pc) {
2647 if(pbl->pc->type == PC_LABEL)
2648 pCodePrintLabel(of, pbl->pc);
2654 genericPrint(of,PCODE(PCI(pc)->cline));
2659 pCode2str(str, 256, pc);
2661 fprintf(of,"%s",str);
2665 fprintf(of, "\t;key=%03x",pc->seq);
2667 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2672 pBranch *dpb = pc->to; // debug
2674 switch ( dpb->pc->type) {
2676 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2679 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2682 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2685 fprintf(of, "\t;flow");
2699 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2700 if(PCW(pc)->pci.label)
2701 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2703 if(PCW(pc)->operand) {
2704 fprintf(of,";\toperand ");
2705 pCodeOpPrint(of,PCW(pc)->operand );
2711 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2712 if(PCFL(pc)->ancestor)
2713 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2720 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2724 fprintf(of,"unknown pCode type %d\n",pc->type);
2729 /*-----------------------------------------------------------------*/
2730 /* pCodePrintFunction - prints function begin/end */
2731 /*-----------------------------------------------------------------*/
2733 static void pCodePrintFunction(FILE *of, pCode *pc)
2739 if( ((pCodeFunction *)pc)->modname)
2740 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2742 if(PCF(pc)->fname) {
2743 pBranch *exits = PCF(pc)->to;
2745 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2748 exits = exits->next;
2751 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2754 if((PCF(pc)->from &&
2755 PCF(pc)->from->pc->type == PC_FUNCTION &&
2756 PCF(PCF(pc)->from->pc)->fname) )
2757 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2759 fprintf(of,"; exit point [can't find entry point]\n");
2762 /*-----------------------------------------------------------------*/
2763 /* pCodePrintLabel - prints label */
2764 /*-----------------------------------------------------------------*/
2766 static void pCodePrintLabel(FILE *of, pCode *pc)
2773 fprintf(of,"%s\n",PCL(pc)->label);
2774 else if (PCL(pc)->key >=0)
2775 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2777 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2780 /*-----------------------------------------------------------------*/
2781 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2782 /* remove it if it is found. */
2783 /*-----------------------------------------------------------------*/
2784 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2791 if(pcl->type == PC_OPCODE)
2792 b = PCI(pcl)->label;
2794 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2799 //fprintf (stderr, "%s \n",__FUNCTION__);
2800 //pcl->print(stderr,pcl);
2801 //pc->print(stderr,pc);
2804 //fprintf (stderr, "found label\n");
2808 bprev->next = b->next; /* Not first pCode in chain */
2812 PCI(pcl)->label = b->next; /* First pCode in chain */
2815 return; /* A label can't occur more than once */
2823 /*-----------------------------------------------------------------*/
2824 /*-----------------------------------------------------------------*/
2825 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2844 /*-----------------------------------------------------------------*/
2845 /* pBranchLink - given two pcodes, this function will link them */
2846 /* together through their pBranches */
2847 /*-----------------------------------------------------------------*/
2848 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2852 // Declare a new branch object for the 'from' pCode.
2854 //_ALLOC(b,sizeof(pBranch));
2855 b = Safe_calloc(1,sizeof(pBranch));
2856 b->pc = PCODE(t); // The link to the 'to' pCode.
2859 f->to = pBranchAppend(f->to,b);
2861 // Now do the same for the 'to' pCode.
2863 //_ALLOC(b,sizeof(pBranch));
2864 b = Safe_calloc(1,sizeof(pBranch));
2868 t->from = pBranchAppend(t->from,b);
2873 /*-----------------------------------------------------------------*/
2874 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2876 /*-----------------------------------------------------------------*/
2877 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2890 /*-----------------------------------------------------------------*/
2891 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2892 /*-----------------------------------------------------------------*/
2893 static void pCodeUnlink(pCode *pc)
2898 if(!pc->prev || !pc->next) {
2899 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2903 /* first remove the pCode from the chain */
2904 pc->prev->next = pc->next;
2905 pc->next->prev = pc->prev;
2907 /* Now for the hard part... */
2909 /* Remove the branches */
2913 pc1 = pb1->pc; /* Get the pCode that branches to the
2914 * one we're unlinking */
2916 /* search for the link back to this pCode (the one we're
2918 if(pb2 = pBranchFind(pc1->to,pc)) {
2919 pb2->pc = pc->to->pc; // make the replacement
2921 /* if the pCode we're unlinking contains multiple 'to'
2922 * branches (e.g. this a skip instruction) then we need
2923 * to copy these extra branches to the chain. */
2925 pBranchAppend(pb2, pc->to->next);
2934 /*-----------------------------------------------------------------*/
2935 /*-----------------------------------------------------------------*/
2937 static void genericAnalyze(pCode *pc)
2947 // Go through the pCodes that are in pCode chain and link
2948 // them together through the pBranches. Note, the pCodes
2949 // are linked together as a contiguous stream like the
2950 // assembly source code lines. The linking here mimics this
2951 // except that comments are not linked in.
2953 pCode *npc = pc->next;
2955 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2956 pBranchLink(pc,npc);
2961 /* reached the end of the pcode chain without finding
2962 * an instruction we could link to. */
2966 fprintf(stderr,"analyze PC_FLOW\n");
2970 fprintf(stderr,,";A bad pCode is being used\n");
2976 /*-----------------------------------------------------------------*/
2977 /*-----------------------------------------------------------------*/
2978 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2982 if(pc->type == PC_LABEL) {
2983 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2986 if(pc->type == PC_OPCODE) {
2987 pbr = PCI(pc)->label;
2989 if(pbr->pc->type == PC_LABEL) {
2990 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3000 /*-----------------------------------------------------------------*/
3001 /*-----------------------------------------------------------------*/
3002 int checkLabel(pCode *pc)
3006 if(pc && isPCI(pc)) {
3007 pbr = PCI(pc)->label;
3009 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3019 /*-----------------------------------------------------------------*/
3020 /* findLabelinpBlock - Search the pCode for a particular label */
3021 /*-----------------------------------------------------------------*/
3022 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3029 for(pc = pb->pcHead; pc; pc = pc->next)
3030 if(compareLabel(pc,pcop_label))
3036 /*-----------------------------------------------------------------*/
3037 /* findLabel - Search the pCode for a particular label */
3038 /*-----------------------------------------------------------------*/
3039 pCode * findLabel(pCodeOpLabel *pcop_label)
3047 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3048 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3052 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3056 /*-----------------------------------------------------------------*/
3057 /* findNextpCode - given a pCode, find the next of type 'pct' */
3058 /* in the linked list */
3059 /*-----------------------------------------------------------------*/
3060 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3073 /*-----------------------------------------------------------------*/
3074 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3075 /* in the linked list */
3076 /*-----------------------------------------------------------------*/
3077 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3089 /*-----------------------------------------------------------------*/
3090 /* findNextInstruction - given a pCode, find the next instruction */
3091 /* in the linked list */
3092 /*-----------------------------------------------------------------*/
3093 pCode * findNextInstruction(pCode *pci)
3098 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3102 fprintf(stderr,"findNextInstruction: ");
3103 printpCode(stderr, pc);
3108 //fprintf(stderr,"Couldn't find instruction\n");
3112 /*-----------------------------------------------------------------*/
3113 /* findNextInstruction - given a pCode, find the next instruction */
3114 /* in the linked list */
3115 /*-----------------------------------------------------------------*/
3116 pCode * findPrevInstruction(pCode *pci)
3118 return findPrevpCode(pci, PC_OPCODE);
3121 /*-----------------------------------------------------------------*/
3122 /* findFunctionEnd - given a pCode find the end of the function */
3123 /* that contains it */
3124 /*-----------------------------------------------------------------*/
3125 pCode * findFunctionEnd(pCode *pc)
3129 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3135 fprintf(stderr,"Couldn't find function end\n");
3140 /*-----------------------------------------------------------------*/
3141 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3142 /* instruction with which it is associated. */
3143 /*-----------------------------------------------------------------*/
3144 static void AnalyzeLabel(pCode *pc)
3153 static void AnalyzeGOTO(pCode *pc)
3156 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3160 static void AnalyzeSKIP(pCode *pc)
3163 pBranchLink(pc,findNextInstruction(pc->next));
3164 pBranchLink(pc,findNextInstruction(pc->next->next));
3168 static void AnalyzeRETURN(pCode *pc)
3171 // branch_link(pc,findFunctionEnd(pc->next));
3177 /*-----------------------------------------------------------------*/
3178 /*-----------------------------------------------------------------*/
3179 regs * getRegFromInstruction(pCode *pc)
3185 PCI(pc)->num_ops == 0 )
3188 switch(PCI(pc)->pcop->type) {
3191 return PCOR(PCI(pc)->pcop)->r;
3193 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3197 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3198 return PCOR(PCI(pc)->pcop)->r;
3201 if(PCOI(PCI(pc)->pcop)->r)
3202 return (PCOI(PCI(pc)->pcop)->r);
3204 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3205 return dirregWithName(PCI(pc)->pcop->name);
3206 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3209 return PCOR(PCI(pc)->pcop)->r;
3212 //fprintf(stderr, "getRegFromInstruction - dir\n");
3213 return PCOR(PCI(pc)->pcop)->r;
3215 //fprintf(stderr, "getRegFromInstruction - literal\n");
3219 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3220 //genericPrint(stderr, pc);
3228 /*-----------------------------------------------------------------*/
3229 /*-----------------------------------------------------------------*/
3231 void AnalyzepBlock(pBlock *pb)
3238 /* Find all of the registers used in this pBlock
3239 * by looking at each instruction and examining it's
3242 for(pc = pb->pcHead; pc; pc = pc->next) {
3244 /* Is this an instruction with operands? */
3245 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3247 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3249 /* Loop through all of the registers declared so far in
3250 this block and see if we find this one there */
3252 regs *r = setFirstItem(pb->tregisters);
3255 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3256 PCOR(PCI(pc)->pcop)->r = r;
3259 r = setNextItem(pb->tregisters);
3263 /* register wasn't found */
3264 //r = Safe_calloc(1, sizeof(regs));
3265 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3266 //addSet(&pb->tregisters, r);
3267 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3268 //PCOR(PCI(pc)->pcop)->r = r;
3269 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3271 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3274 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3275 if(PCOR(PCI(pc)->pcop)->r) {
3276 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3277 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3279 if(PCI(pc)->pcop->name)
3280 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3282 fprintf(stderr,"ERROR: NULL register\n");
3291 /*-----------------------------------------------------------------*/
3293 /*-----------------------------------------------------------------*/
3294 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3296 void InsertpFlow(pCode *pc, pCode **pflow)
3299 PCFL(*pflow)->end = pc;
3301 if(!pc || !pc->next)
3304 *pflow = newpCodeFlow();
3305 pCodeInsertAfter(pc, *pflow);
3308 /*-----------------------------------------------------------------*/
3309 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3310 /* the flow blocks. */
3312 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3313 * point the instruction flow changes.
3315 /*-----------------------------------------------------------------*/
3316 void BuildFlow(pBlock *pb)
3319 pCode *last_pci=NULL;
3326 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3327 /* Insert a pCodeFlow object at the beginning of a pBlock */
3329 InsertpFlow(pb->pcHead, &pflow);
3331 //pflow = newpCodeFlow(); /* Create a new Flow object */
3332 //pflow->next = pb->pcHead; /* Make the current head the next object */
3333 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3334 //pb->pcHead = pflow; /* Make the Flow object the head */
3337 for( pc = findNextInstruction(pb->pcHead);
3339 pc=findNextInstruction(pc)) {
3342 PCI(pc)->pcflow = PCFL(pflow);
3344 //fprintf(stderr," build: ");
3345 //pflow->print(stderr,pflow);
3347 if( PCI(pc)->isSkip) {
3349 /* The two instructions immediately following this one
3350 * mark the beginning of a new flow segment */
3352 while(pc && PCI(pc)->isSkip) {
3354 PCI(pc)->pcflow = PCFL(pflow);
3358 InsertpFlow(pc, &pflow);
3359 pc=findNextInstruction(pc->next);
3367 PCI(pc)->pcflow = PCFL(pflow);
3369 InsertpFlow(pc, &pflow);
3371 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3373 InsertpFlow(pc, &pflow);
3376 } else if (checkLabel(pc)) {
3378 /* This instruction marks the beginning of a
3379 * new flow segment */
3384 /* If the previous pCode is not a flow object, then
3385 * insert a new flow object. (This check prevents
3386 * two consecutive flow objects from being insert in
3387 * the case where a skip instruction preceeds an
3388 * instruction containing a label.) */
3390 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3391 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3393 PCI(pc)->pcflow = PCFL(pflow);
3400 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3402 PCFL(pflow)->end = pb->pcTail;
3405 /*-------------------------------------------------------------------*/
3406 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3407 /* the flow blocks. */
3409 * unBuildFlow removes pCodeFlow objects from a pCode chain
3411 /*-----------------------------------------------------------------*/
3412 void unBuildFlow(pBlock *pb)
3427 if(PCI(pc)->pcflow) {
3428 //free(PCI(pc)->pcflow);
3429 PCI(pc)->pcflow = NULL;
3432 } else if(isPCFL(pc) )
3441 /*-----------------------------------------------------------------*/
3442 /*-----------------------------------------------------------------*/
3443 void dumpCond(int cond)
3446 static char *pcc_str[] = {
3460 int ncond = sizeof(pcc_str) / sizeof(char *);
3463 fprintf(stderr, "0x%04X\n",cond);
3465 for(i=0,j=1; i<ncond; i++, j<<=1)
3467 fprintf(stderr, " %s\n",pcc_str[i]);
3471 /*-----------------------------------------------------------------*/
3472 /*-----------------------------------------------------------------*/
3473 void FlowStats(pCodeFlow *pcflow)
3481 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3483 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3486 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3491 fprintf(stderr, " FlowStats inCond: ");
3492 dumpCond(pcflow->inCond);
3493 fprintf(stderr, " FlowStats outCond: ");
3494 dumpCond(pcflow->outCond);
3498 /*-----------------------------------------------------------------*
3499 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3500 * if it affects the banking bits.
3502 * return: -1 == Banking bits are unaffected by this pCode.
3504 * return: > 0 == Banking bits are affected.
3506 * If the banking bits are affected, then the returned value describes
3507 * which bits are affected and how they're affected. The lower half
3508 * of the integer maps to the bits that are affected, the upper half
3509 * to whether they're set or cleared.
3511 *-----------------------------------------------------------------*/
3512 #define SET_BANK_BIT (1 << 16)
3513 #define CLR_BANK_BIT 0
3515 int isBankInstruction(pCode *pc)
3523 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3525 /* Check to see if the register banks are changing */
3526 if(PCI(pc)->isModReg) {
3528 pCodeOp *pcop = PCI(pc)->pcop;
3529 switch(PCI(pc)->op) {
3532 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3533 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3534 return SET_BANK_BIT | PIC_RP0_BIT;
3537 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3538 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3539 return CLR_BANK_BIT | PIC_RP0_BIT;
3544 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3545 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3546 return CLR_BANK_BIT | PIC_RP1_BIT;
3548 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3549 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3550 return CLR_BANK_BIT | PIC_RP1_BIT;
3554 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3555 //genericPrint(stderr, pc);
3566 /*-----------------------------------------------------------------*/
3567 /*-----------------------------------------------------------------*/
3568 void FillFlow(pCodeFlow *pcflow)
3577 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3579 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3582 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3589 isBankInstruction(pc);
3591 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3595 fprintf(stderr, " FillFlow - Bad end of flow\n");
3597 fprintf(stderr, " FillFlow - Ending flow with\n ");
3598 pc->print(stderr,pc);
3601 fprintf(stderr, " FillFlow inCond: ");
3602 dumpCond(pcflow->inCond);
3603 fprintf(stderr, " FillFlow outCond: ");
3604 dumpCond(pcflow->outCond);
3608 /*-----------------------------------------------------------------*/
3609 /*-----------------------------------------------------------------*/
3610 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3612 pCodeFlowLink *fromLink, *toLink;
3614 if(!from || !to || !to->pcflow || !from->pcflow)
3617 fromLink = newpCodeFlowLink(from->pcflow);
3618 toLink = newpCodeFlowLink(to->pcflow);
3620 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3621 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3625 /*-----------------------------------------------------------------*
3626 * void LinkFlow(pBlock *pb)
3628 * In BuildFlow, the PIC code has been partitioned into contiguous
3629 * non-branching segments. In LinkFlow, we determine the execution
3630 * order of these segments. For example, if one of the segments ends
3631 * with a skip, then we know that there are two possible flow segments
3632 * to which control may be passed.
3633 *-----------------------------------------------------------------*/
3634 void LinkFlow(pBlock *pb)
3640 //fprintf(stderr,"linkflow \n");
3642 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3644 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3647 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3649 //fprintf(stderr," link: ");
3650 //pcflow->print(stderr,pcflow);
3652 //FillFlow(PCFL(pcflow));
3654 pc = PCFL(pcflow)->end;
3656 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3657 if(isPCI_SKIP(pc)) {
3658 //fprintf(stderr, "ends with skip\n");
3659 //pc->print(stderr,pc);
3660 pct=findNextInstruction(pc->next);
3661 LinkFlow_pCode(PCI(pc),PCI(pct));
3662 pct=findNextInstruction(pct->next);
3663 LinkFlow_pCode(PCI(pc),PCI(pct));
3667 if(isPCI_BRANCH(pc)) {
3668 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3670 //fprintf(stderr, "ends with branch\n ");
3671 //pc->print(stderr,pc);
3673 if(!(pcol && isPCOLAB(pcol))) {
3674 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3675 pc->print(stderr,pc);
3676 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3681 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3682 LinkFlow_pCode(PCI(pc),PCI(pct));
3684 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3690 //fprintf(stderr, "ends with non-branching instruction:\n");
3691 //pc->print(stderr,pc);
3693 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3699 //fprintf(stderr, "ends with unknown\n");
3700 //pc->print(stderr,pc);
3704 //fprintf(stderr, "ends with nothing: ERROR\n");
3708 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3713 int isPCinFlow(pCode *pc, pCode *pcflow)
3719 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3722 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3728 /*-----------------------------------------------------------------*/
3729 /*-----------------------------------------------------------------*/
3730 void BanksUsedFlow2(pCode *pcflow)
3739 if(!isPCFL(pcflow)) {
3740 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3744 pc = findNextInstruction(pcflow->next);
3746 PCFL(pcflow)->lastBank = -1;
3748 while(isPCinFlow(pc,pcflow)) {
3750 int bank_selected = isBankInstruction(pc);
3752 //if(PCI(pc)->pcflow)
3753 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3755 if(bank_selected > 0) {
3756 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3758 /* This instruction is modifying banking bits before accessing registers */
3760 PCFL(pcflow)->firstBank = -1;
3762 if(PCFL(pcflow)->lastBank == -1)
3763 PCFL(pcflow)->lastBank = 0;
3765 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3766 if(bank_selected & SET_BANK_BIT)
3767 PCFL(pcflow)->lastBank |= bank;
3771 reg = getRegFromInstruction(pc);
3773 if(reg && !isREGinBank(reg, bank)) {
3774 int allbanks = REGallBanks(reg);
3776 PCFL(pcflow)->firstBank = allbanks;
3778 PCFL(pcflow)->lastBank = allbanks;
3785 pc = findNextInstruction(pc->next);
3788 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3789 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3794 /*-----------------------------------------------------------------*/
3795 /*-----------------------------------------------------------------*/
3796 void BanksUsedFlow(pBlock *pb)
3801 //pb->pcHead->print(stderr, pb->pcHead);
3803 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3804 //pcflow->print(stderr,pcflow);
3806 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3808 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3810 BanksUsedFlow2(pcflow);
3816 /*-----------------------------------------------------------------*/
3817 /*-----------------------------------------------------------------*/
3818 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3826 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3828 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3829 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3831 pCodeInsertAfter(pc->prev, new_pc);
3833 /* Move the label, if there is one */
3835 if(PCI(pc)->label) {
3836 PCI(new_pc)->label = PCI(pc)->label;
3837 PCI(pc)->label = NULL;
3840 /* The new instruction has the same pcflow block */
3841 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3844 /*-----------------------------------------------------------------*/
3845 /*-----------------------------------------------------------------*/
3846 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3857 pc = findNextInstruction(pcfl->pc.next);
3859 while(isPCinFlow(pc,PCODE(pcfl))) {
3862 reg = getRegFromInstruction(pc);
3865 fprintf(stderr, " %s ",reg->name);
3866 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3871 if(reg && REG_BANK(reg)!=cur_bank) {
3872 /* Examine the instruction before this one to make sure it is
3873 * not a skip type instruction */
3874 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3875 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3876 int b = cur_bank ^ REG_BANK(reg);
3878 //fprintf(stderr, "Cool! can switch banks\n");
3879 cur_bank = REG_BANK(reg);
3884 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3887 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3888 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3892 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3893 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3895 insertBankSwitch(pc, -1, -1);
3898 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3899 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3900 pCodeInsertAfter(pc->prev, new_pc);
3901 if(PCI(pc)->label) {
3902 PCI(new_pc)->label = PCI(pc)->label;
3903 PCI(pc)->label = NULL;
3907 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3908 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3909 pCodeInsertAfter(pc, new_pc);
3915 //fprintf(stderr, "Bummer can't switch banks\n");
3921 pc = findNextInstruction(pc->next);
3925 if(pcprev && cur_bank) {
3926 /* Brute force - make sure that we point to bank 0 at the
3927 * end of each flow block */
3928 new_pc = newpCode(POC_BCF,
3929 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3930 pCodeInsertAfter(pcprev, new_pc);
3936 /*-----------------------------------------------------------------*/
3937 /*int compareBankFlow - compare the banking requirements between */
3939 /*-----------------------------------------------------------------*/
3940 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3943 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3946 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3949 if(pcflow->firstBank == -1)
3953 if(pcflowLink->pcflow->firstBank == -1) {
3954 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3955 pcflowLink->pcflow->to :
3956 pcflowLink->pcflow->from);
3957 return compareBankFlow(pcflow, pctl, toORfrom);
3961 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3964 pcflowLink->bank_conflict++;
3965 pcflowLink->pcflow->FromConflicts++;
3966 pcflow->ToConflicts++;
3969 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3972 pcflowLink->bank_conflict++;
3973 pcflowLink->pcflow->ToConflicts++;
3974 pcflow->FromConflicts++;
3978 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3979 pcflowLink->pcflow->pc.seq,
3980 pcflowLink->pcflow->FromConflicts,
3981 pcflowLink->pcflow->ToConflicts);
3986 /*-----------------------------------------------------------------*/
3987 /*-----------------------------------------------------------------*/
3988 void FixBankFlow(pBlock *pb)
3992 pCodeFlowLink *pcfl;
3994 pCode *pcflow_max_To=NULL;
3995 pCode *pcflow_max_From=NULL;
3996 int max_ToConflicts=0;
3997 int max_FromConflicts=0;
3999 //fprintf(stderr,"Fix Bank flow \n");
4000 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4004 First loop through all of the flow objects in this pcode block
4005 and fix the ones that have banking conflicts between the
4009 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4011 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4013 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4015 if(!isPCFL(pcflow)) {
4016 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4020 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4021 PCFL(pcflow)->firstBank >= 0 &&
4022 PCFL(pcflow)->lastBank >= 0 ) {
4024 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4025 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4027 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4028 BanksUsedFlow2(pcflow);
4033 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4035 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4037 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4042 if(!isPCFL(pcflow)) {
4043 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4047 PCFL(pcflow)->FromConflicts = 0;
4048 PCFL(pcflow)->ToConflicts = 0;
4053 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4054 pcfl = setFirstItem(PCFL(pcflow)->from);
4057 pc = PCODE(pcfl->pcflow);
4060 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4061 pc->print(stderr,pc);
4064 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4067 pcfl=setNextItem(PCFL(pcflow)->from);
4070 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4071 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4073 FixRegisterBankingInFlow(PCFL(pcflow),0);
4074 BanksUsedFlow2(pcflow);
4076 continue; /* Don't need to check the flow from here - it's already been fixed */
4083 pcfl = setFirstItem(PCFL(pcflow)->to);
4086 pc = PCODE(pcfl->pcflow);
4088 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4089 pc->print(stderr,pc);
4092 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4095 pcfl=setNextItem(PCFL(pcflow)->to);
4098 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4099 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4101 FixRegisterBankingInFlow(PCFL(pcflow),0);
4102 BanksUsedFlow2(pcflow);
4107 Loop through the flow objects again and find the ones with the
4111 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4113 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4115 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4116 pcflow_max_To = pcflow;
4118 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4119 pcflow_max_From = pcflow;
4123 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4124 PCFL(pcflow_max_To)->pc.seq,
4125 PCFL(pcflow_max_To)->ToConflicts);
4128 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4129 PCFL(pcflow_max_From)->pc.seq,
4130 PCFL(pcflow_max_From)->FromConflicts);
4134 /*-----------------------------------------------------------------*/
4135 /*-----------------------------------------------------------------*/
4136 void DumpFlow(pBlock *pb)
4140 pCodeFlowLink *pcfl;
4143 fprintf(stderr,"Dump flow \n");
4144 pb->pcHead->print(stderr, pb->pcHead);
4146 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4147 pcflow->print(stderr,pcflow);
4149 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4151 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4153 if(!isPCFL(pcflow)) {
4154 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4157 fprintf(stderr,"dumping: ");
4158 pcflow->print(stderr,pcflow);
4159 FlowStats(PCFL(pcflow));
4161 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4163 pc = PCODE(pcfl->pcflow);
4165 fprintf(stderr, " from seq %d:\n",pc->seq);
4167 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4168 pc->print(stderr,pc);
4173 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4175 pc = PCODE(pcfl->pcflow);
4177 fprintf(stderr, " to seq %d:\n",pc->seq);
4179 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4180 pc->print(stderr,pc);
4189 /*-----------------------------------------------------------------*/
4190 /*-----------------------------------------------------------------*/
4191 int OptimizepBlock(pBlock *pb)
4196 if(!pb || !peepOptimizing)
4199 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4201 for(pc = pb->pcHead; pc; pc = pc->next)
4202 matches += pCodePeepMatchRule(pc);
4205 pc = findNextInstruction(pb->pcHead);
4213 if(pCodePeepMatchRule(pc)) {
4218 pc = findNextInstruction(pcprev->next);
4220 pc = findNextInstruction(pb->pcHead);
4222 pc = findNextInstruction(pc->next);
4226 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4231 /*-----------------------------------------------------------------*/
4232 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4233 /*-----------------------------------------------------------------*/
4234 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4238 for(pc = pcs; pc; pc = pc->next) {
4240 if((pc->type == PC_OPCODE) &&
4242 (PCI(pc)->pcop->type == PO_LABEL) &&
4243 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4251 /*-----------------------------------------------------------------*/
4252 /*-----------------------------------------------------------------*/
4253 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4258 (PCI(pc)->pcop->type == PO_LABEL)) {
4260 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4262 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4264 free(pcol->pcop.name);
4266 sprintf(buffer,"_%05d_DS_",pcl->key);
4268 pcol->pcop.name = Safe_strdup(buffer);
4269 pcol->key = pcl->key;
4270 //pc->print(stderr,pc);
4277 /*-----------------------------------------------------------------*/
4278 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4279 /* pCode chain if they're not used. */
4280 /*-----------------------------------------------------------------*/
4281 void pBlockRemoveUnusedLabels(pBlock *pb)
4283 pCode *pc; pCodeLabel *pcl;
4288 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4290 pBranch *pbr = PCI(pc)->label;
4291 if(pbr && pbr->next) {
4292 pCode *pcd = pb->pcHead;
4294 //fprintf(stderr, "multiple labels\n");
4295 //pc->print(stderr,pc);
4300 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4301 //fprintf(stderr,"Used by:\n");
4302 //pcd->print(stderr,pcd);
4304 exchangeLabels(PCL(pbr->pc),pcd);
4313 for(pc = pb->pcHead; pc; pc = pc->next) {
4315 if(isPCL(pc)) // pc->type == PC_LABEL)
4317 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4318 pcl = PCL(PCI(pc)->label->pc);
4321 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4323 /* This pCode is a label, so search the pBlock to see if anyone
4326 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4327 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4328 /* Couldn't find an instruction that refers to this label
4329 * So, unlink the pCode label from it's pCode chain
4330 * and destroy the label */
4331 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4333 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4334 if(pc->type == PC_LABEL) {
4336 pCodeLabelDestruct(pc);
4338 unlinkpCodeFromBranch(pc, PCODE(pcl));
4339 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4350 /*-----------------------------------------------------------------*/
4351 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4352 /* chain and put them into pBranches that are */
4353 /* associated with the appropriate pCode */
4355 /*-----------------------------------------------------------------*/
4356 void pBlockMergeLabels(pBlock *pb)
4359 pCode *pc, *pcnext=NULL;
4364 /* First, Try to remove any unused labels */
4365 //pBlockRemoveUnusedLabels(pb);
4367 /* Now loop through the pBlock and merge the labels with the opcodes */
4370 // for(pc = pb->pcHead; pc; pc = pc->next) {
4373 pCode *pcn = pc->next;
4375 if(pc->type == PC_LABEL) {
4377 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4378 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4379 if((pcnext = findNextInstruction(pc) )) {
4381 // Unlink the pCode label from it's pCode chain
4384 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4385 // And link it into the instruction's pBranch labels. (Note, since
4386 // it's possible to have multiple labels associated with one instruction
4387 // we must provide a means to accomodate the additional labels. Thus
4388 // the labels are placed into the singly-linked list "label" as
4389 // opposed to being a single member of the pCodeInstruction.)
4391 //_ALLOC(pbr,sizeof(pBranch));
4392 pbr = Safe_calloc(1,sizeof(pBranch));
4396 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4399 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4401 } else if(pc->type == PC_CSOURCE) {
4403 /* merge the source line symbolic info into the next instruction */
4404 if((pcnext = findNextInstruction(pc) )) {
4406 // Unlink the pCode label from it's pCode chain
4408 PCI(pcnext)->cline = PCCS(pc);
4409 //fprintf(stderr, "merging CSRC\n");
4410 //genericPrint(stderr,pcnext);
4416 pBlockRemoveUnusedLabels(pb);
4420 /*-----------------------------------------------------------------*/
4421 /*-----------------------------------------------------------------*/
4422 int OptimizepCode(char dbName)
4424 #define MAX_PASSES 4
4433 DFPRINTF((stderr," Optimizing pCode\n"));
4437 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4438 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4439 matches += OptimizepBlock(pb);
4442 while(matches && ++passes < MAX_PASSES);
4447 /*-----------------------------------------------------------------*/
4448 /* popCopyGPR2Bit - copy a pcode operator */
4449 /*-----------------------------------------------------------------*/
4451 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4455 pcop = newpCodeOpBit(pc->name, bitval, 0);
4457 if( !( (pcop->type == PO_LABEL) ||
4458 (pcop->type == PO_LITERAL) ||
4459 (pcop->type == PO_STR) ))
4460 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4468 /*-----------------------------------------------------------------*/
4469 /*-----------------------------------------------------------------*/
4470 int InstructionRegBank(pCode *pc)
4474 if( (reg = getRegFromInstruction(pc)) == NULL)
4477 return REG_BANK(reg);
4482 /*-----------------------------------------------------------------*/
4483 /*-----------------------------------------------------------------*/
4484 void FixRegisterBanking(pBlock *pb)
4496 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4497 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4500 /* loop through all of the flow blocks with in one pblock */
4502 //fprintf(stderr,"Register banking\n");
4505 /* at this point, pc should point to a PC_FLOW object */
4508 /* for each flow block, determine the register banking
4513 //genericPrint(stderr, pc);
4515 reg = getRegFromInstruction(pc);
4518 fprintf(stderr, " %s ",reg->name);
4519 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4523 if(reg && REG_BANK(reg)!=cur_bank) {
4524 /* Examine the instruction before this one to make sure it is
4525 * not a skip type instruction */
4526 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4527 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4528 int b = cur_bank ^ REG_BANK(reg);
4530 //fprintf(stderr, "Cool! can switch banks\n");
4531 cur_bank = REG_BANK(reg);
4533 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4534 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4535 pCodeInsertAfter(pc->prev, new_pc);
4536 if(PCI(pc)->label) {
4537 PCI(new_pc)->label = PCI(pc)->label;
4538 PCI(pc)->label = NULL;
4541 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4542 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4543 pCodeInsertAfter(pc, new_pc);
4549 //fprintf(stderr, "Bummer can't switch banks\n");
4557 // } while(pc && !(isPCFL(pc)));
4562 if(pcprev && cur_bank) {
4563 /* Brute force - make sure that we point to bank 0 at the
4564 * end of each flow block */
4565 new_pc = newpCode(POC_BCF,
4566 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4567 pCodeInsertAfter(pcprev, new_pc);
4573 void pBlockDestruct(pBlock *pb)
4584 /*-----------------------------------------------------------------*/
4585 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4586 /* name dbName and combine them */
4587 /* into one block */
4588 /*-----------------------------------------------------------------*/
4589 void mergepBlocks(char dbName)
4592 pBlock *pb, *pbmerged = NULL,*pbn;
4594 pb = the_pFile->pbHead;
4596 //fprintf(stderr," merging blocks named %c\n",dbName);
4600 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4601 if( getpBlock_dbName(pb) == dbName) {
4603 //fprintf(stderr," merged block %c\n",dbName);
4608 addpCode2pBlock(pbmerged, pb->pcHead);
4609 /* addpCode2pBlock doesn't handle the tail: */
4610 pbmerged->pcTail = pb->pcTail;
4612 pb->prev->next = pbn;
4614 pbn->prev = pb->prev;
4619 //printpBlock(stderr, pbmerged);
4626 /*-----------------------------------------------------------------*/
4627 /* AnalyzeFlow - Examine the flow of the code and optimize */
4629 /* level 0 == minimal optimization */
4630 /* optimize registers that are used only by two instructions */
4631 /* level 1 == maximal optimization */
4632 /* optimize by looking at pairs of instructions that use the */
4634 /*-----------------------------------------------------------------*/
4636 void AnalyzeFlow(int level)
4638 static int times_called=0;
4646 /* if this is not the first time this function has been called,
4647 then clean up old flow information */
4648 if(times_called++) {
4649 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4652 RegsUnMapLiveRanges();
4658 /* Phase 2 - Flow Analysis - Register Banking
4660 * In this phase, the individual flow blocks are examined
4661 * and register banking is fixed.
4664 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4665 //FixRegisterBanking(pb);
4667 /* Phase 2 - Flow Analysis
4669 * In this phase, the pCode is partition into pCodeFlow
4670 * blocks. The flow blocks mark the points where a continuous
4671 * stream of instructions changes flow (e.g. because of
4672 * a call or goto or whatever).
4675 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4679 /* Phase 2 - Flow Analysis - linking flow blocks
4681 * In this phase, the individual flow blocks are examined
4682 * to determine their order of excution.
4685 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4688 /* Phase 3 - Flow Analysis - Flow Tree
4690 * In this phase, the individual flow blocks are examined
4691 * to determine their order of excution.
4694 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4698 /* Phase x - Flow Analysis - Used Banks
4700 * In this phase, the individual flow blocks are examined
4701 * to determine the Register Banks they use
4704 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4708 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4709 pCodeRegMapLiveRanges(pb);
4711 RemoveUnusedRegisters();
4713 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4714 pCodeRegOptimizeRegUsage(level);
4720 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4724 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4726 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4727 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4728 pcflow = pcflow->next) {
4730 FillFlow(PCFL(pcflow));
4735 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4737 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4738 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4739 pcflow = pcflow->next) {
4741 FlowStats(PCFL(pcflow));
4747 /*-----------------------------------------------------------------*/
4748 /* AnalyzeBanking - Called after the memory addresses have been */
4749 /* assigned to the registers. */
4751 /*-----------------------------------------------------------------*/
4753 void AnalyzeBanking(void)
4757 if(!picIsInitialized()) {
4758 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4759 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4760 fprintf(stderr,"support/scripts/inc2h.pl\n");
4761 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4766 /* Phase x - Flow Analysis - Used Banks
4768 * In this phase, the individual flow blocks are examined
4769 * to determine the Register Banks they use
4775 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4777 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4778 FixRegisterBanking(pb);
4782 /*-----------------------------------------------------------------*/
4783 /* buildCallTree - look at the flow and extract all of the calls */
4785 /*-----------------------------------------------------------------*/
4786 set *register_usage(pBlock *pb);
4788 void buildCallTree(void )
4799 /* Now build the call tree.
4800 First we examine all of the pCodes for functions.
4801 Keep in mind that the function boundaries coincide
4802 with pBlock boundaries.
4804 The algorithm goes something like this:
4805 We have two nested loops. The outer loop iterates
4806 through all of the pBlocks/functions. The inner
4807 loop iterates through all of the pCodes for
4808 a given pBlock. When we begin iterating through
4809 a pBlock, the variable pc_fstart, pCode of the start
4810 of a function, is cleared. We then search for pCodes
4811 of type PC_FUNCTION. When one is encountered, we
4812 initialize pc_fstart to this and at the same time
4813 associate a new pBranch object that signifies a
4814 branch entry. If a return is found, then this signifies
4815 a function exit point. We'll link the pCodes of these
4816 returns to the matching pc_fstart.
4818 When we're done, a doubly linked list of pBranches
4819 will exist. The head of this list is stored in
4820 `the_pFile', which is the meta structure for all
4821 of the pCode. Look at the printCallTree function
4822 on how the pBranches are linked together.
4825 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4826 pCode *pc_fstart=NULL;
4827 for(pc = pb->pcHead; pc; pc = pc->next) {
4829 if (PCF(pc)->fname) {
4831 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4832 //fprintf(stderr," found main \n");
4833 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4837 pbr = Safe_calloc(1,sizeof(pBranch));
4838 pbr->pc = pc_fstart = pc;
4841 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4843 // Here's a better way of doing the same:
4844 addSet(&pb->function_entries, pc);
4847 // Found an exit point in a function, e.g. return
4848 // (Note, there may be more than one return per function)
4850 pBranchLink(PCF(pc_fstart), PCF(pc));
4852 addSet(&pb->function_exits, pc);
4854 } else if(isCALL(pc)) {
4855 addSet(&pb->function_calls,pc);
4860 /* Re-allocate the registers so that there are no collisions
4861 * between local variables when one function call another */
4864 // pic14_deallocateAllRegs();
4866 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4873 /*-----------------------------------------------------------------*/
4874 /* AnalyzepCode - parse the pCode that has been generated and form */
4875 /* all of the logical connections. */
4877 /* Essentially what's done here is that the pCode flow is */
4879 /*-----------------------------------------------------------------*/
4881 void AnalyzepCode(char dbName)
4892 /* Phase 1 - Register allocation and peep hole optimization
4894 * The first part of the analysis is to determine the registers
4895 * that are used in the pCode. Once that is done, the peep rules
4896 * are applied to the code. We continue to loop until no more
4897 * peep rule optimizations are found (or until we exceed the
4898 * MAX_PASSES threshold).
4900 * When done, the required registers will be determined.
4906 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4907 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4909 /* First, merge the labels with the instructions */
4910 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4911 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4913 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4914 //fprintf(stderr," analyze and merging block %c\n",dbName);
4915 pBlockMergeLabels(pb);
4918 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4922 changes = OptimizepCode(dbName);
4924 } while(changes && (i++ < MAX_PASSES));
4929 /*-----------------------------------------------------------------*/
4930 /* ispCodeFunction - returns true if *pc is the pCode of a */
4932 /*-----------------------------------------------------------------*/
4933 bool ispCodeFunction(pCode *pc)
4936 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4942 /*-----------------------------------------------------------------*/
4943 /* findFunction - Search for a function by name (given the name) */
4944 /* in the set of all functions that are in a pBlock */
4945 /* (note - I expect this to change because I'm planning to limit */
4946 /* pBlock's to just one function declaration */
4947 /*-----------------------------------------------------------------*/
4948 pCode *findFunction(char *fname)
4955 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4957 pc = setFirstItem(pb->function_entries);
4960 if((pc->type == PC_FUNCTION) &&
4962 (strcmp(fname, PCF(pc)->fname)==0))
4965 pc = setNextItem(pb->function_entries);
4973 void MarkUsedRegisters(set *regset)
4978 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4979 r2 = pic14_regWithIdx(r1->rIdx);
4985 void pBlockStats(FILE *of, pBlock *pb)
4991 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4993 // for now just print the first element of each set
4994 pc = setFirstItem(pb->function_entries);
4996 fprintf(of,";entry: ");
4999 pc = setFirstItem(pb->function_exits);
5001 fprintf(of,";has an exit\n");
5005 pc = setFirstItem(pb->function_calls);
5007 fprintf(of,";functions called:\n");
5010 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5011 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5013 pc = setNextItem(pb->function_calls);
5017 r = setFirstItem(pb->tregisters);
5019 int n = elementsInSet(pb->tregisters);
5021 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5024 fprintf(of,"; %s\n",r->name);
5025 r = setNextItem(pb->tregisters);
5030 /*-----------------------------------------------------------------*/
5031 /*-----------------------------------------------------------------*/
5033 static void sequencepCode(void)
5039 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5041 pb->seq = GpCodeSequenceNumber+1;
5043 for( pc = pb->pcHead; pc; pc = pc->next)
5044 pc->seq = ++GpCodeSequenceNumber;
5050 /*-----------------------------------------------------------------*/
5051 /*-----------------------------------------------------------------*/
5052 set *register_usage(pBlock *pb)
5055 set *registers=NULL;
5056 set *registersInCallPath = NULL;
5058 /* check recursion */
5060 pc = setFirstItem(pb->function_entries);
5067 if(pc->type != PC_FUNCTION)
5068 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5070 pc = setFirstItem(pb->function_calls);
5071 for( ; pc; pc = setNextItem(pb->function_calls)) {
5073 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5074 char *dest = get_op_from_instruction(PCI(pc));
5076 pcn = findFunction(dest);
5078 registersInCallPath = register_usage(pcn->pb);
5080 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5085 pBlockStats(stderr,pb); // debug
5088 // Mark the registers in this block as used.
5090 MarkUsedRegisters(pb->tregisters);
5091 if(registersInCallPath) {
5092 /* registers were used in the functions this pBlock has called */
5093 /* so now, we need to see if these collide with the ones we are */
5096 regs *r1,*r2, *newreg;
5098 DFPRINTF((stderr,"comparing registers\n"));
5100 r1 = setFirstItem(registersInCallPath);
5103 r2 = setFirstItem(pb->tregisters);
5105 while(r2 && (r1->type != REG_STK)) {
5107 if(r2->rIdx == r1->rIdx) {
5108 newreg = pic14_findFreeReg(REG_GPR);
5112 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5116 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5117 r1->rIdx, newreg->rIdx));
5118 r2->rIdx = newreg->rIdx;
5119 //if(r2->name) free(r2->name);
5121 r2->name = Safe_strdup(newreg->name);
5125 newreg->wasUsed = 1;
5127 r2 = setNextItem(pb->tregisters);
5130 r1 = setNextItem(registersInCallPath);
5133 /* Collisions have been resolved. Now free the registers in the call path */
5134 r1 = setFirstItem(registersInCallPath);
5136 if(r1->type != REG_STK) {
5137 newreg = pic14_regWithIdx(r1->rIdx);
5140 r1 = setNextItem(registersInCallPath);
5144 // MarkUsedRegisters(pb->registers);
5146 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5149 DFPRINTF((stderr,"returning regs\n"));
5151 DFPRINTF((stderr,"not returning regs\n"));
5153 DFPRINTF((stderr,"pBlock after register optim.\n"));
5154 pBlockStats(stderr,pb); // debug
5160 /*-----------------------------------------------------------------*/
5161 /* printCallTree - writes the call tree to a file */
5163 /*-----------------------------------------------------------------*/
5164 void pct2(FILE *of,pBlock *pb,int indent)
5168 // set *registersInCallPath = NULL;
5174 return; //recursion ?
5176 pc = setFirstItem(pb->function_entries);
5183 for(i=0;i<indent;i++) // Indentation
5186 if(pc->type == PC_FUNCTION)
5187 fprintf(of,"%s\n",PCF(pc)->fname);
5192 pc = setFirstItem(pb->function_calls);
5193 for( ; pc; pc = setNextItem(pb->function_calls)) {
5195 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5196 char *dest = get_op_from_instruction(PCI(pc));
5198 pcn = findFunction(dest);
5200 pct2(of,pcn->pb,indent+1);
5202 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5210 /*-----------------------------------------------------------------*/
5211 /* printCallTree - writes the call tree to a file */
5213 /*-----------------------------------------------------------------*/
5215 void printCallTree(FILE *of)
5227 fprintf(of, "\npBlock statistics\n");
5228 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5233 fprintf(of,"Call Tree\n");
5234 pbr = the_pFile->functions;
5238 if(!ispCodeFunction(pc))
5239 fprintf(of,"bug in call tree");
5242 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5244 while(pc->next && !ispCodeFunction(pc->next)) {
5246 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5247 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5255 fprintf(of,"\n**************\n\na better call tree\n");
5256 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5261 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5262 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5268 /*-----------------------------------------------------------------*/
5270 /*-----------------------------------------------------------------*/
5272 void InlineFunction(pBlock *pb)
5280 pc = setFirstItem(pb->function_calls);
5282 for( ; pc; pc = setNextItem(pb->function_calls)) {
5285 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5291 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5293 //fprintf(stderr,"Cool can inline:\n");
5294 //pcn->print(stderr,pcn);
5296 //fprintf(stderr,"recursive call Inline\n");
5297 InlineFunction(pcn->pb);
5298 //fprintf(stderr,"return from recursive call Inline\n");
5301 At this point, *pc points to a CALL mnemonic, and
5302 *pcn points to the function that is being called.
5304 To in-line this call, we need to remove the CALL
5305 and RETURN(s), and link the function pCode in with
5311 /* Remove the CALL */
5315 /* remove callee pBlock from the pBlock linked list */
5316 removepBlock(pcn->pb);
5324 /* Remove the Function pCode */
5325 pct = findNextInstruction(pcn->next);
5327 /* Link the function with the callee */
5328 pc->next = pcn->next;
5329 pcn->next->prev = pc;
5331 /* Convert the function name into a label */
5333 pbr = Safe_calloc(1,sizeof(pBranch));
5334 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5336 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5337 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5339 /* turn all of the return's except the last into goto's */
5340 /* check case for 2 instruction pBlocks */
5341 pce = findNextInstruction(pcn->next);
5343 pCode *pce_next = findNextInstruction(pce->next);
5345 if(pce_next == NULL) {
5346 /* found the last return */
5347 pCode *pc_call_next = findNextInstruction(pc_call->next);
5349 //fprintf(stderr,"found last return\n");
5350 //pce->print(stderr,pce);
5351 pce->prev->next = pc_call->next;
5352 pc_call->next->prev = pce->prev;
5353 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5363 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5369 /*-----------------------------------------------------------------*/
5371 /*-----------------------------------------------------------------*/
5373 void InlinepCode(void)
5382 if(!functionInlining)
5385 /* Loop through all of the function definitions and count the
5386 * number of times each one is called */
5387 //fprintf(stderr,"inlining %d\n",__LINE__);
5389 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5391 pc = setFirstItem(pb->function_calls);
5393 for( ; pc; pc = setNextItem(pb->function_calls)) {
5396 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5397 if(pcn && isPCF(pcn)) {
5398 PCF(pcn)->ncalled++;
5401 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5406 //fprintf(stderr,"inlining %d\n",__LINE__);
5408 /* Now, Loop through the function definitions again, but this
5409 * time inline those functions that have only been called once. */
5411 InlineFunction(the_pFile->pbHead);
5412 //fprintf(stderr,"inlining %d\n",__LINE__);
5414 for(pb = the_pFile->pbHead; pb; pb = pb->next)