1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
78 int debug_verbose = 0; /* Set true to inundate .asm file */
80 static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
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) || (pci->isBitInst))
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);
1934 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?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;
2010 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2014 /*-----------------------------------------------------------------*/
2015 /*-----------------------------------------------------------------*/
2016 pCodeOp *newpCodeOpLit(int lit)
2022 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2023 pcop->type = PO_LITERAL;
2027 sprintf(s,"0x%02x",lit);
2029 pcop->name = Safe_strdup(s);
2032 ((pCodeOpLit *)pcop)->lit = lit;
2037 /*-----------------------------------------------------------------*/
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2043 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2044 pcop->type = PO_IMMEDIATE;
2046 regs *r = dirregWithName(name);
2047 pcop->name = Safe_strdup(name);
2050 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2051 PCOI(pcop)->rIdx = r->rIdx;
2053 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2054 PCOI(pcop)->rIdx = -1;
2056 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2061 PCOI(pcop)->index = index;
2062 PCOI(pcop)->offset = offset;
2063 PCOI(pcop)->_const = code_space;
2068 /*-----------------------------------------------------------------*/
2069 /*-----------------------------------------------------------------*/
2070 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2076 if(!pcwb || !subtype) {
2077 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2081 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2082 pcop->type = PO_WILD;
2083 sprintf(s,"%%%d",id);
2084 pcop->name = Safe_strdup(s);
2086 PCOW(pcop)->id = id;
2087 PCOW(pcop)->pcwb = pcwb;
2088 PCOW(pcop)->subtype = subtype;
2089 PCOW(pcop)->matched = NULL;
2094 /*-----------------------------------------------------------------*/
2095 /*-----------------------------------------------------------------*/
2096 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2100 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2101 pcop->type = PO_GPR_BIT;
2103 pcop->name = Safe_strdup(s);
2107 PCORB(pcop)->bit = bit;
2108 PCORB(pcop)->inBitSpace = inBitSpace;
2110 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2111 PCOR(pcop)->r = NULL;
2112 PCOR(pcop)->rIdx = 0;
2116 /*-----------------------------------------------------------------*
2117 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2119 * If rIdx >=0 then a specific register from the set of registers
2120 * will be selected. If rIdx <0, then a new register will be searched
2122 *-----------------------------------------------------------------*/
2124 pCodeOp *newpCodeOpReg(int rIdx)
2128 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2133 PCOR(pcop)->rIdx = rIdx;
2134 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2136 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2139 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2142 pcop->type = PCOR(pcop)->r->pc_type;
2147 pCodeOp *newpCodeOpRegFromStr(char *name)
2151 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2152 PCOR(pcop)->r = allocRegByName(name, 1);
2153 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2154 pcop->type = PCOR(pcop)->r->pc_type;
2155 pcop->name = PCOR(pcop)->r->name;
2160 /*-----------------------------------------------------------------*/
2161 /*-----------------------------------------------------------------*/
2163 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2170 pcop = newpCodeOpBit(name, -1,0);
2174 pcop = newpCodeOpLit(-1);
2178 pcop = newpCodeOpLabel(NULL,-1);
2181 pcop = newpCodeOpReg(-1);
2184 case PO_GPR_REGISTER:
2186 pcop = newpCodeOpRegFromStr(name);
2188 pcop = newpCodeOpReg(-1);
2192 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2195 pcop->name = Safe_strdup(name);
2203 /*-----------------------------------------------------------------*/
2204 /*-----------------------------------------------------------------*/
2205 void pCodeConstString(char *name, char *value)
2209 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2214 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2218 sprintf(buffer,"; %s = %s",name,value);
2220 addpCode2pBlock(pb,newpCodeCharP(buffer));
2221 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2224 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2230 /*-----------------------------------------------------------------*/
2231 /*-----------------------------------------------------------------*/
2232 void pCodeReadCodeTable(void)
2236 fprintf(stderr, " %s\n",__FUNCTION__);
2238 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2242 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2243 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2244 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2245 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2247 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2248 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2249 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2250 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2255 /*-----------------------------------------------------------------*/
2256 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2257 /*-----------------------------------------------------------------*/
2258 void addpCode2pBlock(pBlock *pb, pCode *pc)
2265 /* If this is the first pcode to be added to a block that
2266 * was initialized with a NULL pcode, then go ahead and
2267 * make this pcode the head and tail */
2268 pb->pcHead = pb->pcTail = pc;
2271 pb->pcTail->next = pc;
2273 pc->prev = pb->pcTail;
2280 /*-----------------------------------------------------------------*/
2281 /* addpBlock - place a pBlock into the pFile */
2282 /*-----------------------------------------------------------------*/
2283 void addpBlock(pBlock *pb)
2285 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2288 /* First time called, we'll pass through here. */
2289 //_ALLOC(the_pFile,sizeof(pFile));
2290 the_pFile = Safe_calloc(1,sizeof(pFile));
2291 the_pFile->pbHead = the_pFile->pbTail = pb;
2292 the_pFile->functions = NULL;
2296 the_pFile->pbTail->next = pb;
2297 pb->prev = the_pFile->pbTail;
2299 the_pFile->pbTail = pb;
2302 /*-----------------------------------------------------------------*/
2303 /* removepBlock - remove a pBlock from the pFile */
2304 /*-----------------------------------------------------------------*/
2305 void removepBlock(pBlock *pb)
2313 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2315 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2318 if(pbs == the_pFile->pbHead)
2319 the_pFile->pbHead = pbs->next;
2321 if (pbs == the_pFile->pbTail)
2322 the_pFile->pbTail = pbs->prev;
2325 pbs->next->prev = pbs->prev;
2328 pbs->prev->next = pbs->next;
2335 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2339 /*-----------------------------------------------------------------*/
2340 /* printpCode - write the contents of a pCode to a file */
2341 /*-----------------------------------------------------------------*/
2342 void printpCode(FILE *of, pCode *pc)
2353 fprintf(of,"warning - unable to print pCode\n");
2356 /*-----------------------------------------------------------------*/
2357 /* printpBlock - write the contents of a pBlock to a file */
2358 /*-----------------------------------------------------------------*/
2359 void printpBlock(FILE *of, pBlock *pb)
2369 for(pc = pb->pcHead; pc; pc = pc->next)
2374 /*-----------------------------------------------------------------*/
2376 /* pCode processing */
2380 /*-----------------------------------------------------------------*/
2382 void unlinkpCode(pCode *pc)
2388 fprintf(stderr,"Unlinking: ");
2389 printpCode(stderr, pc);
2392 pc->prev->next = pc->next;
2394 pc->next->prev = pc->prev;
2396 pc->prev = pc->next = NULL;
2400 /*-----------------------------------------------------------------*/
2401 /*-----------------------------------------------------------------*/
2403 static void genericDestruct(pCode *pc)
2409 /* For instructions, tell the register (if there's one used)
2410 * that it's no longer needed */
2411 regs *reg = getRegFromInstruction(pc);
2413 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2416 /* Instead of deleting the memory used by this pCode, mark
2417 * the object as bad so that if there's a pointer to this pCode
2418 * dangling around somewhere then (hopefully) when the type is
2419 * checked we'll catch it.
2424 addpCode2pBlock(pb_dead_pcodes, pc);
2431 /*-----------------------------------------------------------------*/
2432 /*-----------------------------------------------------------------*/
2433 void pBlockRegs(FILE *of, pBlock *pb)
2438 r = setFirstItem(pb->tregisters);
2440 r = setNextItem(pb->tregisters);
2445 /*-----------------------------------------------------------------*/
2446 /*-----------------------------------------------------------------*/
2447 char *get_op(pCodeOp *pcop,char *buffer, int size)
2452 int use_buffer = 1; // copy the string to the passed buffer pointer
2457 use_buffer = 0; // Don't bother copying the string to the buffer.
2461 switch(pcop->type) {
2465 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2468 return PCOR(pcop)->r->name;
2471 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2474 SAFE_snprintf(&buffer,&size,"%s",r->name);
2484 if(PCOI(pcop)->_const) {
2486 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2487 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2490 8 * PCOI(pcop)->offset );
2492 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2495 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2496 SAFE_snprintf(&s,&size,"(%s + %d)",
2498 PCOI(pcop)->index );
2500 SAFE_snprintf(&s,&size,"%s",pcop->name);
2507 //size = sizeof(buffer);
2508 if( PCOR(pcop)->instance) {
2509 SAFE_snprintf(&s,&size,"(%s + %d)",
2511 PCOR(pcop)->instance );
2512 //fprintf(stderr,"PO_DIR %s\n",buffer);
2514 SAFE_snprintf(&s,&size,"%s",pcop->name);
2520 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2529 return "NO operand";
2533 /*-----------------------------------------------------------------*/
2534 /*-----------------------------------------------------------------*/
2535 static char *get_op_from_instruction( pCodeInstruction *pcc)
2539 return get_op(pcc->pcop,NULL,0);
2541 return ("ERROR Null: "__FUNCTION__);
2545 /*-----------------------------------------------------------------*/
2546 /*-----------------------------------------------------------------*/
2547 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2550 fprintf(of,"pcodeopprint- not implemented\n");
2553 /*-----------------------------------------------------------------*/
2554 /*-----------------------------------------------------------------*/
2555 char *pCode2str(char *str, int size, pCode *pc)
2563 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2565 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2567 if(PCI(pc)->isBitInst) {
2568 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2569 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2570 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2571 PCI(pc)->pcop->name ,
2572 PCI(pc)->pcop->name );
2574 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2575 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2576 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2577 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2579 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2580 //PCI(pc)->pcop->t.bit );
2583 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2584 if( PCI(pc)->num_ops == 2)
2585 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2587 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2590 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2592 if( PCI(pc)->num_ops == 2)
2593 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2601 /* assuming that comment ends with a \n */
2602 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2606 /* assuming that inline code ends with a \n */
2607 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2611 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2614 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2617 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2620 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2623 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2627 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2634 /*-----------------------------------------------------------------*/
2635 /* genericPrint - the contents of a pCode to a file */
2636 /*-----------------------------------------------------------------*/
2637 static void genericPrint(FILE *of, pCode *pc)
2645 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2649 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2653 // If the opcode has a label, print that first
2655 pBranch *pbl = PCI(pc)->label;
2656 while(pbl && pbl->pc) {
2657 if(pbl->pc->type == PC_LABEL)
2658 pCodePrintLabel(of, pbl->pc);
2664 genericPrint(of,PCODE(PCI(pc)->cline));
2669 pCode2str(str, 256, pc);
2671 fprintf(of,"%s",str);
2675 fprintf(of, "\t;key=%03x",pc->seq);
2677 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2682 pBranch *dpb = pc->to; // debug
2684 switch ( dpb->pc->type) {
2686 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2689 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2692 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2695 fprintf(of, "\t;flow");
2709 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2710 if(PCW(pc)->pci.label)
2711 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2713 if(PCW(pc)->operand) {
2714 fprintf(of,";\toperand ");
2715 pCodeOpPrint(of,PCW(pc)->operand );
2721 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2722 if(PCFL(pc)->ancestor)
2723 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2730 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2734 fprintf(of,"unknown pCode type %d\n",pc->type);
2739 /*-----------------------------------------------------------------*/
2740 /* pCodePrintFunction - prints function begin/end */
2741 /*-----------------------------------------------------------------*/
2743 static void pCodePrintFunction(FILE *of, pCode *pc)
2749 if( ((pCodeFunction *)pc)->modname)
2750 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2752 if(PCF(pc)->fname) {
2753 pBranch *exits = PCF(pc)->to;
2755 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2758 exits = exits->next;
2761 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2764 if((PCF(pc)->from &&
2765 PCF(pc)->from->pc->type == PC_FUNCTION &&
2766 PCF(PCF(pc)->from->pc)->fname) )
2767 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2769 fprintf(of,"; exit point [can't find entry point]\n");
2772 /*-----------------------------------------------------------------*/
2773 /* pCodePrintLabel - prints label */
2774 /*-----------------------------------------------------------------*/
2776 static void pCodePrintLabel(FILE *of, pCode *pc)
2783 fprintf(of,"%s\n",PCL(pc)->label);
2784 else if (PCL(pc)->key >=0)
2785 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2787 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2790 /*-----------------------------------------------------------------*/
2791 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2792 /* remove it if it is found. */
2793 /*-----------------------------------------------------------------*/
2794 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2801 if(pcl->type == PC_OPCODE)
2802 b = PCI(pcl)->label;
2804 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2809 //fprintf (stderr, "%s \n",__FUNCTION__);
2810 //pcl->print(stderr,pcl);
2811 //pc->print(stderr,pc);
2814 //fprintf (stderr, "found label\n");
2818 bprev->next = b->next; /* Not first pCode in chain */
2822 PCI(pcl)->label = b->next; /* First pCode in chain */
2825 return; /* A label can't occur more than once */
2833 /*-----------------------------------------------------------------*/
2834 /*-----------------------------------------------------------------*/
2835 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2854 /*-----------------------------------------------------------------*/
2855 /* pBranchLink - given two pcodes, this function will link them */
2856 /* together through their pBranches */
2857 /*-----------------------------------------------------------------*/
2858 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2862 // Declare a new branch object for the 'from' pCode.
2864 //_ALLOC(b,sizeof(pBranch));
2865 b = Safe_calloc(1,sizeof(pBranch));
2866 b->pc = PCODE(t); // The link to the 'to' pCode.
2869 f->to = pBranchAppend(f->to,b);
2871 // Now do the same for the 'to' pCode.
2873 //_ALLOC(b,sizeof(pBranch));
2874 b = Safe_calloc(1,sizeof(pBranch));
2878 t->from = pBranchAppend(t->from,b);
2883 /*-----------------------------------------------------------------*/
2884 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2886 /*-----------------------------------------------------------------*/
2887 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2900 /*-----------------------------------------------------------------*/
2901 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2902 /*-----------------------------------------------------------------*/
2903 static void pCodeUnlink(pCode *pc)
2908 if(!pc->prev || !pc->next) {
2909 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2913 /* first remove the pCode from the chain */
2914 pc->prev->next = pc->next;
2915 pc->next->prev = pc->prev;
2917 /* Now for the hard part... */
2919 /* Remove the branches */
2923 pc1 = pb1->pc; /* Get the pCode that branches to the
2924 * one we're unlinking */
2926 /* search for the link back to this pCode (the one we're
2928 if(pb2 = pBranchFind(pc1->to,pc)) {
2929 pb2->pc = pc->to->pc; // make the replacement
2931 /* if the pCode we're unlinking contains multiple 'to'
2932 * branches (e.g. this a skip instruction) then we need
2933 * to copy these extra branches to the chain. */
2935 pBranchAppend(pb2, pc->to->next);
2944 /*-----------------------------------------------------------------*/
2945 /*-----------------------------------------------------------------*/
2947 static void genericAnalyze(pCode *pc)
2957 // Go through the pCodes that are in pCode chain and link
2958 // them together through the pBranches. Note, the pCodes
2959 // are linked together as a contiguous stream like the
2960 // assembly source code lines. The linking here mimics this
2961 // except that comments are not linked in.
2963 pCode *npc = pc->next;
2965 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2966 pBranchLink(pc,npc);
2971 /* reached the end of the pcode chain without finding
2972 * an instruction we could link to. */
2976 fprintf(stderr,"analyze PC_FLOW\n");
2980 fprintf(stderr,,";A bad pCode is being used\n");
2986 /*-----------------------------------------------------------------*/
2987 /*-----------------------------------------------------------------*/
2988 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2992 if(pc->type == PC_LABEL) {
2993 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2996 if(pc->type == PC_OPCODE) {
2997 pbr = PCI(pc)->label;
2999 if(pbr->pc->type == PC_LABEL) {
3000 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3010 /*-----------------------------------------------------------------*/
3011 /*-----------------------------------------------------------------*/
3012 int checkLabel(pCode *pc)
3016 if(pc && isPCI(pc)) {
3017 pbr = PCI(pc)->label;
3019 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3029 /*-----------------------------------------------------------------*/
3030 /* findLabelinpBlock - Search the pCode for a particular label */
3031 /*-----------------------------------------------------------------*/
3032 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3039 for(pc = pb->pcHead; pc; pc = pc->next)
3040 if(compareLabel(pc,pcop_label))
3046 /*-----------------------------------------------------------------*/
3047 /* findLabel - Search the pCode for a particular label */
3048 /*-----------------------------------------------------------------*/
3049 pCode * findLabel(pCodeOpLabel *pcop_label)
3057 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3058 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3062 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3066 /*-----------------------------------------------------------------*/
3067 /* findNextpCode - given a pCode, find the next of type 'pct' */
3068 /* in the linked list */
3069 /*-----------------------------------------------------------------*/
3070 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3083 /*-----------------------------------------------------------------*/
3084 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3085 /* in the linked list */
3086 /*-----------------------------------------------------------------*/
3087 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3099 /*-----------------------------------------------------------------*/
3100 /* findNextInstruction - given a pCode, find the next instruction */
3101 /* in the linked list */
3102 /*-----------------------------------------------------------------*/
3103 pCode * findNextInstruction(pCode *pci)
3108 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3112 fprintf(stderr,"findNextInstruction: ");
3113 printpCode(stderr, pc);
3118 //fprintf(stderr,"Couldn't find instruction\n");
3122 /*-----------------------------------------------------------------*/
3123 /* findNextInstruction - given a pCode, find the next instruction */
3124 /* in the linked list */
3125 /*-----------------------------------------------------------------*/
3126 pCode * findPrevInstruction(pCode *pci)
3128 return findPrevpCode(pci, PC_OPCODE);
3131 /*-----------------------------------------------------------------*/
3132 /* findFunctionEnd - given a pCode find the end of the function */
3133 /* that contains it */
3134 /*-----------------------------------------------------------------*/
3135 pCode * findFunctionEnd(pCode *pc)
3139 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3145 fprintf(stderr,"Couldn't find function end\n");
3150 /*-----------------------------------------------------------------*/
3151 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3152 /* instruction with which it is associated. */
3153 /*-----------------------------------------------------------------*/
3154 static void AnalyzeLabel(pCode *pc)
3163 static void AnalyzeGOTO(pCode *pc)
3166 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3170 static void AnalyzeSKIP(pCode *pc)
3173 pBranchLink(pc,findNextInstruction(pc->next));
3174 pBranchLink(pc,findNextInstruction(pc->next->next));
3178 static void AnalyzeRETURN(pCode *pc)
3181 // branch_link(pc,findFunctionEnd(pc->next));
3187 /*-----------------------------------------------------------------*/
3188 /*-----------------------------------------------------------------*/
3189 regs * getRegFromInstruction(pCode *pc)
3195 PCI(pc)->num_ops == 0 )
3198 switch(PCI(pc)->pcop->type) {
3201 return PCOR(PCI(pc)->pcop)->r;
3203 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3207 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3208 return PCOR(PCI(pc)->pcop)->r;
3211 if(PCOI(PCI(pc)->pcop)->r)
3212 return (PCOI(PCI(pc)->pcop)->r);
3214 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3215 return dirregWithName(PCI(pc)->pcop->name);
3216 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3219 return PCOR(PCI(pc)->pcop)->r;
3222 //fprintf(stderr, "getRegFromInstruction - dir\n");
3223 return PCOR(PCI(pc)->pcop)->r;
3225 //fprintf(stderr, "getRegFromInstruction - literal\n");
3229 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3230 //genericPrint(stderr, pc);
3238 /*-----------------------------------------------------------------*/
3239 /*-----------------------------------------------------------------*/
3241 void AnalyzepBlock(pBlock *pb)
3248 /* Find all of the registers used in this pBlock
3249 * by looking at each instruction and examining it's
3252 for(pc = pb->pcHead; pc; pc = pc->next) {
3254 /* Is this an instruction with operands? */
3255 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3257 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3259 /* Loop through all of the registers declared so far in
3260 this block and see if we find this one there */
3262 regs *r = setFirstItem(pb->tregisters);
3265 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3266 PCOR(PCI(pc)->pcop)->r = r;
3269 r = setNextItem(pb->tregisters);
3273 /* register wasn't found */
3274 //r = Safe_calloc(1, sizeof(regs));
3275 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3276 //addSet(&pb->tregisters, r);
3277 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3278 //PCOR(PCI(pc)->pcop)->r = r;
3279 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3281 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3284 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3285 if(PCOR(PCI(pc)->pcop)->r) {
3286 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3287 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3289 if(PCI(pc)->pcop->name)
3290 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3292 fprintf(stderr,"ERROR: NULL register\n");
3301 /*-----------------------------------------------------------------*/
3303 /*-----------------------------------------------------------------*/
3304 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3306 void InsertpFlow(pCode *pc, pCode **pflow)
3309 PCFL(*pflow)->end = pc;
3311 if(!pc || !pc->next)
3314 *pflow = newpCodeFlow();
3315 pCodeInsertAfter(pc, *pflow);
3318 /*-----------------------------------------------------------------*/
3319 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3320 /* the flow blocks. */
3322 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3323 * point the instruction flow changes.
3325 /*-----------------------------------------------------------------*/
3326 void BuildFlow(pBlock *pb)
3329 pCode *last_pci=NULL;
3336 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3337 /* Insert a pCodeFlow object at the beginning of a pBlock */
3339 InsertpFlow(pb->pcHead, &pflow);
3341 //pflow = newpCodeFlow(); /* Create a new Flow object */
3342 //pflow->next = pb->pcHead; /* Make the current head the next object */
3343 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3344 //pb->pcHead = pflow; /* Make the Flow object the head */
3347 for( pc = findNextInstruction(pb->pcHead);
3349 pc=findNextInstruction(pc)) {
3352 PCI(pc)->pcflow = PCFL(pflow);
3354 //fprintf(stderr," build: ");
3355 //pflow->print(stderr,pflow);
3357 if( PCI(pc)->isSkip) {
3359 /* The two instructions immediately following this one
3360 * mark the beginning of a new flow segment */
3362 while(pc && PCI(pc)->isSkip) {
3364 PCI(pc)->pcflow = PCFL(pflow);
3368 InsertpFlow(pc, &pflow);
3369 pc=findNextInstruction(pc->next);
3377 PCI(pc)->pcflow = PCFL(pflow);
3379 InsertpFlow(pc, &pflow);
3381 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3383 InsertpFlow(pc, &pflow);
3386 } else if (checkLabel(pc)) {
3388 /* This instruction marks the beginning of a
3389 * new flow segment */
3394 /* If the previous pCode is not a flow object, then
3395 * insert a new flow object. (This check prevents
3396 * two consecutive flow objects from being insert in
3397 * the case where a skip instruction preceeds an
3398 * instruction containing a label.) */
3400 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3401 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3403 PCI(pc)->pcflow = PCFL(pflow);
3410 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3412 PCFL(pflow)->end = pb->pcTail;
3415 /*-------------------------------------------------------------------*/
3416 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3417 /* the flow blocks. */
3419 * unBuildFlow removes pCodeFlow objects from a pCode chain
3421 /*-----------------------------------------------------------------*/
3422 void unBuildFlow(pBlock *pb)
3437 if(PCI(pc)->pcflow) {
3438 //free(PCI(pc)->pcflow);
3439 PCI(pc)->pcflow = NULL;
3442 } else if(isPCFL(pc) )
3451 /*-----------------------------------------------------------------*/
3452 /*-----------------------------------------------------------------*/
3453 void dumpCond(int cond)
3456 static char *pcc_str[] = {
3470 int ncond = sizeof(pcc_str) / sizeof(char *);
3473 fprintf(stderr, "0x%04X\n",cond);
3475 for(i=0,j=1; i<ncond; i++, j<<=1)
3477 fprintf(stderr, " %s\n",pcc_str[i]);
3481 /*-----------------------------------------------------------------*/
3482 /*-----------------------------------------------------------------*/
3483 void FlowStats(pCodeFlow *pcflow)
3491 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3493 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3496 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3501 fprintf(stderr, " FlowStats inCond: ");
3502 dumpCond(pcflow->inCond);
3503 fprintf(stderr, " FlowStats outCond: ");
3504 dumpCond(pcflow->outCond);
3508 /*-----------------------------------------------------------------*
3509 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3510 * if it affects the banking bits.
3512 * return: -1 == Banking bits are unaffected by this pCode.
3514 * return: > 0 == Banking bits are affected.
3516 * If the banking bits are affected, then the returned value describes
3517 * which bits are affected and how they're affected. The lower half
3518 * of the integer maps to the bits that are affected, the upper half
3519 * to whether they're set or cleared.
3521 *-----------------------------------------------------------------*/
3522 #define SET_BANK_BIT (1 << 16)
3523 #define CLR_BANK_BIT 0
3525 int isBankInstruction(pCode *pc)
3533 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3535 /* Check to see if the register banks are changing */
3536 if(PCI(pc)->isModReg) {
3538 pCodeOp *pcop = PCI(pc)->pcop;
3539 switch(PCI(pc)->op) {
3542 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3543 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3544 return SET_BANK_BIT | PIC_RP0_BIT;
3547 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3548 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3549 return CLR_BANK_BIT | PIC_RP0_BIT;
3554 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3555 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3556 return CLR_BANK_BIT | PIC_RP1_BIT;
3558 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3559 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3560 return CLR_BANK_BIT | PIC_RP1_BIT;
3564 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3565 //genericPrint(stderr, pc);
3576 /*-----------------------------------------------------------------*/
3577 /*-----------------------------------------------------------------*/
3578 void FillFlow(pCodeFlow *pcflow)
3587 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3589 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3592 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3599 isBankInstruction(pc);
3601 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3605 fprintf(stderr, " FillFlow - Bad end of flow\n");
3607 fprintf(stderr, " FillFlow - Ending flow with\n ");
3608 pc->print(stderr,pc);
3611 fprintf(stderr, " FillFlow inCond: ");
3612 dumpCond(pcflow->inCond);
3613 fprintf(stderr, " FillFlow outCond: ");
3614 dumpCond(pcflow->outCond);
3618 /*-----------------------------------------------------------------*/
3619 /*-----------------------------------------------------------------*/
3620 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3622 pCodeFlowLink *fromLink, *toLink;
3624 if(!from || !to || !to->pcflow || !from->pcflow)
3627 fromLink = newpCodeFlowLink(from->pcflow);
3628 toLink = newpCodeFlowLink(to->pcflow);
3630 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3631 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3635 /*-----------------------------------------------------------------*
3636 * void LinkFlow(pBlock *pb)
3638 * In BuildFlow, the PIC code has been partitioned into contiguous
3639 * non-branching segments. In LinkFlow, we determine the execution
3640 * order of these segments. For example, if one of the segments ends
3641 * with a skip, then we know that there are two possible flow segments
3642 * to which control may be passed.
3643 *-----------------------------------------------------------------*/
3644 void LinkFlow(pBlock *pb)
3650 //fprintf(stderr,"linkflow \n");
3652 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3654 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3657 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3659 //fprintf(stderr," link: ");
3660 //pcflow->print(stderr,pcflow);
3662 //FillFlow(PCFL(pcflow));
3664 pc = PCFL(pcflow)->end;
3666 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3667 if(isPCI_SKIP(pc)) {
3668 //fprintf(stderr, "ends with skip\n");
3669 //pc->print(stderr,pc);
3670 pct=findNextInstruction(pc->next);
3671 LinkFlow_pCode(PCI(pc),PCI(pct));
3672 pct=findNextInstruction(pct->next);
3673 LinkFlow_pCode(PCI(pc),PCI(pct));
3677 if(isPCI_BRANCH(pc)) {
3678 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3680 //fprintf(stderr, "ends with branch\n ");
3681 //pc->print(stderr,pc);
3683 if(!(pcol && isPCOLAB(pcol))) {
3684 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3685 pc->print(stderr,pc);
3686 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3691 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3692 LinkFlow_pCode(PCI(pc),PCI(pct));
3694 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3695 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3696 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3702 //fprintf(stderr, "ends with non-branching instruction:\n");
3703 //pc->print(stderr,pc);
3705 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3711 //fprintf(stderr, "ends with unknown\n");
3712 //pc->print(stderr,pc);
3716 //fprintf(stderr, "ends with nothing: ERROR\n");
3720 /*-----------------------------------------------------------------*/
3721 /*-----------------------------------------------------------------*/
3723 /*-----------------------------------------------------------------*/
3724 /*-----------------------------------------------------------------*/
3725 int isPCinFlow(pCode *pc, pCode *pcflow)
3731 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3734 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3740 /*-----------------------------------------------------------------*/
3741 /*-----------------------------------------------------------------*/
3742 void BanksUsedFlow2(pCode *pcflow)
3751 if(!isPCFL(pcflow)) {
3752 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3756 pc = findNextInstruction(pcflow->next);
3758 PCFL(pcflow)->lastBank = -1;
3760 while(isPCinFlow(pc,pcflow)) {
3762 int bank_selected = isBankInstruction(pc);
3764 //if(PCI(pc)->pcflow)
3765 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3767 if(bank_selected > 0) {
3768 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3770 /* This instruction is modifying banking bits before accessing registers */
3772 PCFL(pcflow)->firstBank = -1;
3774 if(PCFL(pcflow)->lastBank == -1)
3775 PCFL(pcflow)->lastBank = 0;
3777 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3778 if(bank_selected & SET_BANK_BIT)
3779 PCFL(pcflow)->lastBank |= bank;
3783 reg = getRegFromInstruction(pc);
3785 if(reg && !isREGinBank(reg, bank)) {
3786 int allbanks = REGallBanks(reg);
3788 PCFL(pcflow)->firstBank = allbanks;
3790 PCFL(pcflow)->lastBank = allbanks;
3797 pc = findNextInstruction(pc->next);
3800 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3801 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3806 /*-----------------------------------------------------------------*/
3807 /*-----------------------------------------------------------------*/
3808 void BanksUsedFlow(pBlock *pb)
3813 //pb->pcHead->print(stderr, pb->pcHead);
3815 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3816 //pcflow->print(stderr,pcflow);
3818 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3820 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3822 BanksUsedFlow2(pcflow);
3828 /*-----------------------------------------------------------------*/
3829 /*-----------------------------------------------------------------*/
3830 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3838 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3840 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3841 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3844 /* insert the bank switch after this pc instruction */
3845 pCode *pcnext = findNextInstruction(pc);
3846 pCodeInsertAfter(pc, new_pc);
3851 pCodeInsertAfter(pc->prev, new_pc);
3853 /* Move the label, if there is one */
3855 if(PCI(pc)->label) {
3856 PCI(new_pc)->label = PCI(pc)->label;
3857 PCI(pc)->label = NULL;
3860 /* The new instruction has the same pcflow block */
3861 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3864 /*-----------------------------------------------------------------*/
3865 /*-----------------------------------------------------------------*/
3866 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3877 pc = findNextInstruction(pcfl->pc.next);
3879 while(isPCinFlow(pc,PCODE(pcfl))) {
3881 reg = getRegFromInstruction(pc);
3884 fprintf(stderr, " %s ",reg->name);
3885 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3890 if((reg && REG_BANK(reg)!=cur_bank) ||
3891 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) )) {
3893 /* Examine the instruction before this one to make sure it is
3894 * not a skip type instruction */
3895 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3897 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3901 reg_bank = (reg) ? REG_BANK(reg) : 0;
3903 b = cur_bank ^ reg_bank;
3905 //fprintf(stderr, "Cool! can switch banks\n");
3906 cur_bank = reg_bank;
3911 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3914 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3915 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3919 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3920 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3922 insertBankSwitch(0, pc, -1, -1);
3928 //fprintf(stderr, "Bummer can't switch banks\n");
3934 pc = findNextInstruction(pc->next);
3938 if(pcprev && cur_bank) {
3939 /* Brute force - make sure that we point to bank 0 at the
3940 * end of each flow block */
3941 new_pc = newpCode(POC_BCF,
3942 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3943 pCodeInsertAfter(pcprev, new_pc);
3949 /*-----------------------------------------------------------------*/
3950 /*int compareBankFlow - compare the banking requirements between */
3952 /*-----------------------------------------------------------------*/
3953 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3956 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3959 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3962 if(pcflow->firstBank == -1)
3966 if(pcflowLink->pcflow->firstBank == -1) {
3967 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3968 pcflowLink->pcflow->to :
3969 pcflowLink->pcflow->from);
3970 return compareBankFlow(pcflow, pctl, toORfrom);
3974 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3977 pcflowLink->bank_conflict++;
3978 pcflowLink->pcflow->FromConflicts++;
3979 pcflow->ToConflicts++;
3982 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3985 pcflowLink->bank_conflict++;
3986 pcflowLink->pcflow->ToConflicts++;
3987 pcflow->FromConflicts++;
3991 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3992 pcflowLink->pcflow->pc.seq,
3993 pcflowLink->pcflow->FromConflicts,
3994 pcflowLink->pcflow->ToConflicts);
3999 /*-----------------------------------------------------------------*/
4000 /*-----------------------------------------------------------------*/
4001 void FixBankFlow(pBlock *pb)
4005 pCodeFlowLink *pcfl;
4007 pCode *pcflow_max_To=NULL;
4008 pCode *pcflow_max_From=NULL;
4009 int max_ToConflicts=0;
4010 int max_FromConflicts=0;
4012 //fprintf(stderr,"Fix Bank flow \n");
4013 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4017 First loop through all of the flow objects in this pcode block
4018 and fix the ones that have banking conflicts between the
4022 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4024 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4026 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4028 if(!isPCFL(pcflow)) {
4029 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4033 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4034 PCFL(pcflow)->firstBank >= 0 &&
4035 PCFL(pcflow)->lastBank >= 0 ) {
4037 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4038 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4040 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4041 BanksUsedFlow2(pcflow);
4046 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4048 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4050 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4055 if(!isPCFL(pcflow)) {
4056 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4060 PCFL(pcflow)->FromConflicts = 0;
4061 PCFL(pcflow)->ToConflicts = 0;
4066 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4067 pcfl = setFirstItem(PCFL(pcflow)->from);
4070 pc = PCODE(pcfl->pcflow);
4073 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4074 pc->print(stderr,pc);
4077 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4080 pcfl=setNextItem(PCFL(pcflow)->from);
4083 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4084 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4086 FixRegisterBankingInFlow(PCFL(pcflow),0);
4087 BanksUsedFlow2(pcflow);
4089 continue; /* Don't need to check the flow from here - it's already been fixed */
4096 pcfl = setFirstItem(PCFL(pcflow)->to);
4099 pc = PCODE(pcfl->pcflow);
4101 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4102 pc->print(stderr,pc);
4105 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4108 pcfl=setNextItem(PCFL(pcflow)->to);
4111 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4112 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4114 FixRegisterBankingInFlow(PCFL(pcflow),0);
4115 BanksUsedFlow2(pcflow);
4120 Loop through the flow objects again and find the ones with the
4124 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4126 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4128 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4129 pcflow_max_To = pcflow;
4131 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4132 pcflow_max_From = pcflow;
4136 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4137 PCFL(pcflow_max_To)->pc.seq,
4138 PCFL(pcflow_max_To)->ToConflicts);
4141 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4142 PCFL(pcflow_max_From)->pc.seq,
4143 PCFL(pcflow_max_From)->FromConflicts);
4147 /*-----------------------------------------------------------------*/
4148 /*-----------------------------------------------------------------*/
4149 void DumpFlow(pBlock *pb)
4153 pCodeFlowLink *pcfl;
4156 fprintf(stderr,"Dump flow \n");
4157 pb->pcHead->print(stderr, pb->pcHead);
4159 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4160 pcflow->print(stderr,pcflow);
4162 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4164 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4166 if(!isPCFL(pcflow)) {
4167 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4170 fprintf(stderr,"dumping: ");
4171 pcflow->print(stderr,pcflow);
4172 FlowStats(PCFL(pcflow));
4174 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4176 pc = PCODE(pcfl->pcflow);
4178 fprintf(stderr, " from seq %d:\n",pc->seq);
4180 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4181 pc->print(stderr,pc);
4186 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4188 pc = PCODE(pcfl->pcflow);
4190 fprintf(stderr, " to seq %d:\n",pc->seq);
4192 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4193 pc->print(stderr,pc);
4202 /*-----------------------------------------------------------------*/
4203 /*-----------------------------------------------------------------*/
4204 int OptimizepBlock(pBlock *pb)
4209 if(!pb || !peepOptimizing)
4212 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4214 for(pc = pb->pcHead; pc; pc = pc->next)
4215 matches += pCodePeepMatchRule(pc);
4218 pc = findNextInstruction(pb->pcHead);
4226 if(pCodePeepMatchRule(pc)) {
4231 pc = findNextInstruction(pcprev->next);
4233 pc = findNextInstruction(pb->pcHead);
4235 pc = findNextInstruction(pc->next);
4239 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4244 /*-----------------------------------------------------------------*/
4245 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4246 /*-----------------------------------------------------------------*/
4247 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4251 for(pc = pcs; pc; pc = pc->next) {
4253 if((pc->type == PC_OPCODE) &&
4255 (PCI(pc)->pcop->type == PO_LABEL) &&
4256 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4264 /*-----------------------------------------------------------------*/
4265 /*-----------------------------------------------------------------*/
4266 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4273 (PCI(pc)->pcop->type == PO_LABEL)) {
4275 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4277 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4279 free(pcol->pcop.name);
4281 /* If the key is negative, then we (probably) have a label to
4282 * a function and the name is already defined */
4285 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4289 //sprintf(buffer,"_%05d_DS_",pcl->key);
4291 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4293 pcol->pcop.name = Safe_strdup(s);
4294 pcol->key = pcl->key;
4295 //pc->print(stderr,pc);
4302 /*-----------------------------------------------------------------*/
4303 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4304 /* pCode chain if they're not used. */
4305 /*-----------------------------------------------------------------*/
4306 void pBlockRemoveUnusedLabels(pBlock *pb)
4308 pCode *pc; pCodeLabel *pcl;
4313 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4315 pBranch *pbr = PCI(pc)->label;
4316 if(pbr && pbr->next) {
4317 pCode *pcd = pb->pcHead;
4319 //fprintf(stderr, "multiple labels\n");
4320 //pc->print(stderr,pc);
4325 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4326 //fprintf(stderr,"Used by:\n");
4327 //pcd->print(stderr,pcd);
4329 exchangeLabels(PCL(pbr->pc),pcd);
4338 for(pc = pb->pcHead; pc; pc = pc->next) {
4340 if(isPCL(pc)) // pc->type == PC_LABEL)
4342 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4343 pcl = PCL(PCI(pc)->label->pc);
4346 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4348 /* This pCode is a label, so search the pBlock to see if anyone
4351 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4352 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4353 /* Couldn't find an instruction that refers to this label
4354 * So, unlink the pCode label from it's pCode chain
4355 * and destroy the label */
4356 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4358 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4359 if(pc->type == PC_LABEL) {
4361 pCodeLabelDestruct(pc);
4363 unlinkpCodeFromBranch(pc, PCODE(pcl));
4364 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4375 /*-----------------------------------------------------------------*/
4376 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4377 /* chain and put them into pBranches that are */
4378 /* associated with the appropriate pCode */
4380 /*-----------------------------------------------------------------*/
4381 void pBlockMergeLabels(pBlock *pb)
4384 pCode *pc, *pcnext=NULL;
4389 /* First, Try to remove any unused labels */
4390 //pBlockRemoveUnusedLabels(pb);
4392 /* Now loop through the pBlock and merge the labels with the opcodes */
4395 // for(pc = pb->pcHead; pc; pc = pc->next) {
4398 pCode *pcn = pc->next;
4400 if(pc->type == PC_LABEL) {
4402 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4403 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4404 if((pcnext = findNextInstruction(pc) )) {
4406 // Unlink the pCode label from it's pCode chain
4409 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4410 // And link it into the instruction's pBranch labels. (Note, since
4411 // it's possible to have multiple labels associated with one instruction
4412 // we must provide a means to accomodate the additional labels. Thus
4413 // the labels are placed into the singly-linked list "label" as
4414 // opposed to being a single member of the pCodeInstruction.)
4416 //_ALLOC(pbr,sizeof(pBranch));
4417 pbr = Safe_calloc(1,sizeof(pBranch));
4421 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4424 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4426 } else if(pc->type == PC_CSOURCE) {
4428 /* merge the source line symbolic info into the next instruction */
4429 if((pcnext = findNextInstruction(pc) )) {
4431 // Unlink the pCode label from it's pCode chain
4433 PCI(pcnext)->cline = PCCS(pc);
4434 //fprintf(stderr, "merging CSRC\n");
4435 //genericPrint(stderr,pcnext);
4441 pBlockRemoveUnusedLabels(pb);
4445 /*-----------------------------------------------------------------*/
4446 /*-----------------------------------------------------------------*/
4447 int OptimizepCode(char dbName)
4449 #define MAX_PASSES 4
4458 DFPRINTF((stderr," Optimizing pCode\n"));
4462 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4463 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4464 matches += OptimizepBlock(pb);
4467 while(matches && ++passes < MAX_PASSES);
4472 /*-----------------------------------------------------------------*/
4473 /* popCopyGPR2Bit - copy a pcode operator */
4474 /*-----------------------------------------------------------------*/
4476 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4480 pcop = newpCodeOpBit(pc->name, bitval, 0);
4482 if( !( (pcop->type == PO_LABEL) ||
4483 (pcop->type == PO_LITERAL) ||
4484 (pcop->type == PO_STR) ))
4485 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4493 /*-----------------------------------------------------------------*/
4494 /*-----------------------------------------------------------------*/
4495 int InstructionRegBank(pCode *pc)
4499 if( (reg = getRegFromInstruction(pc)) == NULL)
4502 return REG_BANK(reg);
4507 /*-----------------------------------------------------------------*/
4508 /*-----------------------------------------------------------------*/
4509 void FixRegisterBanking(pBlock *pb)
4520 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4521 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4524 /* loop through all of the flow blocks with in one pblock */
4526 //fprintf(stderr,"Register banking\n");
4529 /* at this point, pc should point to a PC_FLOW object */
4532 /* for each flow block, determine the register banking
4537 //genericPrint(stderr, pc);
4539 reg = getRegFromInstruction(pc);
4542 fprintf(stderr, " %s ",reg->name);
4543 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4544 reg->address,REG_BANK(reg),reg->isBitField);
4549 if((reg && REG_BANK(reg)!=cur_bank) ||
4550 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) )) {
4552 /* Examine the instruction before this one to make sure it is
4553 * not a skip type instruction */
4554 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4556 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4560 reg_bank = (reg) ? REG_BANK(reg) : 0;
4562 b = cur_bank ^ reg_bank;
4564 cur_bank = reg_bank;
4569 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4572 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4573 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4577 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4578 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4580 insertBankSwitch(0, pc, -1, -1);
4586 //fprintf(stderr, "Bummer can't switch banks\n");
4596 // } while(pc && !(isPCFL(pc)));
4601 if(pcprev && cur_bank) {
4603 int pos = 1; /* Assume that the bank swithc instruction(s)
4604 * are inserted after this instruction */
4606 if((PCI(pcprev)->op == POC_RETLW) ||
4607 (PCI(pcprev)->op == POC_RETURN) ||
4608 (PCI(pcprev)->op == POC_RETFIE)) {
4610 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4616 /* Brute force - make sure that we point to bank 0 at the
4617 * end of each flow block */
4619 switch(cur_bank & 3) {
4623 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4626 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4627 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4630 insertBankSwitch(pos, pcprev, -1, -1);
4635 new_pc = newpCode(POC_BCF,
4636 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4637 pCodeInsertAfter(pcprev, new_pc);
4640 //fprintf(stderr, "Brute force switch\n");
4649 if(reg && REG_BANK(reg)!=cur_bank) {
4650 //fprintf(stderr,"need to switch banks\n");
4651 /* Examine the instruction before this one to make sure it is
4652 * not a skip type instruction */
4653 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4654 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4655 int b = cur_bank ^ REG_BANK(reg);
4657 cur_bank = REG_BANK(reg);
4663 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4666 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4667 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4671 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4672 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4674 insertBankSwitch(0, pc, -1, -1);
4683 void pBlockDestruct(pBlock *pb)
4694 /*-----------------------------------------------------------------*/
4695 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4696 /* name dbName and combine them */
4697 /* into one block */
4698 /*-----------------------------------------------------------------*/
4699 void mergepBlocks(char dbName)
4702 pBlock *pb, *pbmerged = NULL,*pbn;
4704 pb = the_pFile->pbHead;
4706 //fprintf(stderr," merging blocks named %c\n",dbName);
4710 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4711 if( getpBlock_dbName(pb) == dbName) {
4713 //fprintf(stderr," merged block %c\n",dbName);
4718 addpCode2pBlock(pbmerged, pb->pcHead);
4719 /* addpCode2pBlock doesn't handle the tail: */
4720 pbmerged->pcTail = pb->pcTail;
4722 pb->prev->next = pbn;
4724 pbn->prev = pb->prev;
4729 //printpBlock(stderr, pbmerged);
4736 /*-----------------------------------------------------------------*/
4737 /* AnalyzeFlow - Examine the flow of the code and optimize */
4739 /* level 0 == minimal optimization */
4740 /* optimize registers that are used only by two instructions */
4741 /* level 1 == maximal optimization */
4742 /* optimize by looking at pairs of instructions that use the */
4744 /*-----------------------------------------------------------------*/
4746 void AnalyzeFlow(int level)
4748 static int times_called=0;
4756 /* if this is not the first time this function has been called,
4757 then clean up old flow information */
4758 if(times_called++) {
4759 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4762 RegsUnMapLiveRanges();
4768 /* Phase 2 - Flow Analysis - Register Banking
4770 * In this phase, the individual flow blocks are examined
4771 * and register banking is fixed.
4774 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4775 //FixRegisterBanking(pb);
4777 /* Phase 2 - Flow Analysis
4779 * In this phase, the pCode is partition into pCodeFlow
4780 * blocks. The flow blocks mark the points where a continuous
4781 * stream of instructions changes flow (e.g. because of
4782 * a call or goto or whatever).
4785 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4789 /* Phase 2 - Flow Analysis - linking flow blocks
4791 * In this phase, the individual flow blocks are examined
4792 * to determine their order of excution.
4795 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4798 /* Phase 3 - Flow Analysis - Flow Tree
4800 * In this phase, the individual flow blocks are examined
4801 * to determine their order of excution.
4804 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4808 /* Phase x - Flow Analysis - Used Banks
4810 * In this phase, the individual flow blocks are examined
4811 * to determine the Register Banks they use
4814 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4818 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4819 pCodeRegMapLiveRanges(pb);
4821 RemoveUnusedRegisters();
4823 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4824 pCodeRegOptimizeRegUsage(level);
4830 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4834 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4836 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4837 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4838 pcflow = pcflow->next) {
4840 FillFlow(PCFL(pcflow));
4845 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4847 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4848 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4849 pcflow = pcflow->next) {
4851 FlowStats(PCFL(pcflow));
4857 /*-----------------------------------------------------------------*/
4858 /* AnalyzeBanking - Called after the memory addresses have been */
4859 /* assigned to the registers. */
4861 /*-----------------------------------------------------------------*/
4863 void AnalyzeBanking(void)
4867 if(!picIsInitialized()) {
4868 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4869 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4870 fprintf(stderr,"support/scripts/inc2h.pl\n");
4871 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4876 /* Phase x - Flow Analysis - Used Banks
4878 * In this phase, the individual flow blocks are examined
4879 * to determine the Register Banks they use
4885 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4887 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4888 FixRegisterBanking(pb);
4892 /*-----------------------------------------------------------------*/
4893 /* buildCallTree - look at the flow and extract all of the calls */
4895 /*-----------------------------------------------------------------*/
4896 set *register_usage(pBlock *pb);
4898 void buildCallTree(void )
4909 /* Now build the call tree.
4910 First we examine all of the pCodes for functions.
4911 Keep in mind that the function boundaries coincide
4912 with pBlock boundaries.
4914 The algorithm goes something like this:
4915 We have two nested loops. The outer loop iterates
4916 through all of the pBlocks/functions. The inner
4917 loop iterates through all of the pCodes for
4918 a given pBlock. When we begin iterating through
4919 a pBlock, the variable pc_fstart, pCode of the start
4920 of a function, is cleared. We then search for pCodes
4921 of type PC_FUNCTION. When one is encountered, we
4922 initialize pc_fstart to this and at the same time
4923 associate a new pBranch object that signifies a
4924 branch entry. If a return is found, then this signifies
4925 a function exit point. We'll link the pCodes of these
4926 returns to the matching pc_fstart.
4928 When we're done, a doubly linked list of pBranches
4929 will exist. The head of this list is stored in
4930 `the_pFile', which is the meta structure for all
4931 of the pCode. Look at the printCallTree function
4932 on how the pBranches are linked together.
4935 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4936 pCode *pc_fstart=NULL;
4937 for(pc = pb->pcHead; pc; pc = pc->next) {
4939 if (PCF(pc)->fname) {
4941 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4942 //fprintf(stderr," found main \n");
4943 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4947 pbr = Safe_calloc(1,sizeof(pBranch));
4948 pbr->pc = pc_fstart = pc;
4951 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4953 // Here's a better way of doing the same:
4954 addSet(&pb->function_entries, pc);
4957 // Found an exit point in a function, e.g. return
4958 // (Note, there may be more than one return per function)
4960 pBranchLink(PCF(pc_fstart), PCF(pc));
4962 addSet(&pb->function_exits, pc);
4964 } else if(isCALL(pc)) {
4965 addSet(&pb->function_calls,pc);
4970 /* Re-allocate the registers so that there are no collisions
4971 * between local variables when one function call another */
4974 // pic14_deallocateAllRegs();
4976 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4983 /*-----------------------------------------------------------------*/
4984 /* AnalyzepCode - parse the pCode that has been generated and form */
4985 /* all of the logical connections. */
4987 /* Essentially what's done here is that the pCode flow is */
4989 /*-----------------------------------------------------------------*/
4991 void AnalyzepCode(char dbName)
5002 /* Phase 1 - Register allocation and peep hole optimization
5004 * The first part of the analysis is to determine the registers
5005 * that are used in the pCode. Once that is done, the peep rules
5006 * are applied to the code. We continue to loop until no more
5007 * peep rule optimizations are found (or until we exceed the
5008 * MAX_PASSES threshold).
5010 * When done, the required registers will be determined.
5016 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5017 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5019 /* First, merge the labels with the instructions */
5020 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5021 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5023 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5024 //fprintf(stderr," analyze and merging block %c\n",dbName);
5025 pBlockMergeLabels(pb);
5028 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5032 changes = OptimizepCode(dbName);
5034 } while(changes && (i++ < MAX_PASSES));
5039 /*-----------------------------------------------------------------*/
5040 /* ispCodeFunction - returns true if *pc is the pCode of a */
5042 /*-----------------------------------------------------------------*/
5043 bool ispCodeFunction(pCode *pc)
5046 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5052 /*-----------------------------------------------------------------*/
5053 /* findFunction - Search for a function by name (given the name) */
5054 /* in the set of all functions that are in a pBlock */
5055 /* (note - I expect this to change because I'm planning to limit */
5056 /* pBlock's to just one function declaration */
5057 /*-----------------------------------------------------------------*/
5058 pCode *findFunction(char *fname)
5065 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5067 pc = setFirstItem(pb->function_entries);
5070 if((pc->type == PC_FUNCTION) &&
5072 (strcmp(fname, PCF(pc)->fname)==0))
5075 pc = setNextItem(pb->function_entries);
5083 void MarkUsedRegisters(set *regset)
5088 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5089 r2 = pic14_regWithIdx(r1->rIdx);
5095 void pBlockStats(FILE *of, pBlock *pb)
5101 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5103 // for now just print the first element of each set
5104 pc = setFirstItem(pb->function_entries);
5106 fprintf(of,";entry: ");
5109 pc = setFirstItem(pb->function_exits);
5111 fprintf(of,";has an exit\n");
5115 pc = setFirstItem(pb->function_calls);
5117 fprintf(of,";functions called:\n");
5120 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5121 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5123 pc = setNextItem(pb->function_calls);
5127 r = setFirstItem(pb->tregisters);
5129 int n = elementsInSet(pb->tregisters);
5131 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5134 fprintf(of,"; %s\n",r->name);
5135 r = setNextItem(pb->tregisters);
5140 /*-----------------------------------------------------------------*/
5141 /*-----------------------------------------------------------------*/
5143 static void sequencepCode(void)
5149 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5151 pb->seq = GpCodeSequenceNumber+1;
5153 for( pc = pb->pcHead; pc; pc = pc->next)
5154 pc->seq = ++GpCodeSequenceNumber;
5160 /*-----------------------------------------------------------------*/
5161 /*-----------------------------------------------------------------*/
5162 set *register_usage(pBlock *pb)
5165 set *registers=NULL;
5166 set *registersInCallPath = NULL;
5168 /* check recursion */
5170 pc = setFirstItem(pb->function_entries);
5177 if(pc->type != PC_FUNCTION)
5178 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5180 pc = setFirstItem(pb->function_calls);
5181 for( ; pc; pc = setNextItem(pb->function_calls)) {
5183 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5184 char *dest = get_op_from_instruction(PCI(pc));
5186 pcn = findFunction(dest);
5188 registersInCallPath = register_usage(pcn->pb);
5190 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5195 pBlockStats(stderr,pb); // debug
5198 // Mark the registers in this block as used.
5200 MarkUsedRegisters(pb->tregisters);
5201 if(registersInCallPath) {
5202 /* registers were used in the functions this pBlock has called */
5203 /* so now, we need to see if these collide with the ones we are */
5206 regs *r1,*r2, *newreg;
5208 DFPRINTF((stderr,"comparing registers\n"));
5210 r1 = setFirstItem(registersInCallPath);
5213 r2 = setFirstItem(pb->tregisters);
5215 while(r2 && (r1->type != REG_STK)) {
5217 if(r2->rIdx == r1->rIdx) {
5218 newreg = pic14_findFreeReg(REG_GPR);
5222 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5226 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5227 r1->rIdx, newreg->rIdx));
5228 r2->rIdx = newreg->rIdx;
5229 //if(r2->name) free(r2->name);
5231 r2->name = Safe_strdup(newreg->name);
5235 newreg->wasUsed = 1;
5237 r2 = setNextItem(pb->tregisters);
5240 r1 = setNextItem(registersInCallPath);
5243 /* Collisions have been resolved. Now free the registers in the call path */
5244 r1 = setFirstItem(registersInCallPath);
5246 if(r1->type != REG_STK) {
5247 newreg = pic14_regWithIdx(r1->rIdx);
5250 r1 = setNextItem(registersInCallPath);
5254 // MarkUsedRegisters(pb->registers);
5256 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5259 DFPRINTF((stderr,"returning regs\n"));
5261 DFPRINTF((stderr,"not returning regs\n"));
5263 DFPRINTF((stderr,"pBlock after register optim.\n"));
5264 pBlockStats(stderr,pb); // debug
5270 /*-----------------------------------------------------------------*/
5271 /* printCallTree - writes the call tree to a file */
5273 /*-----------------------------------------------------------------*/
5274 void pct2(FILE *of,pBlock *pb,int indent)
5278 // set *registersInCallPath = NULL;
5284 return; //recursion ?
5286 pc = setFirstItem(pb->function_entries);
5293 for(i=0;i<indent;i++) // Indentation
5296 if(pc->type == PC_FUNCTION)
5297 fprintf(of,"%s\n",PCF(pc)->fname);
5302 pc = setFirstItem(pb->function_calls);
5303 for( ; pc; pc = setNextItem(pb->function_calls)) {
5305 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5306 char *dest = get_op_from_instruction(PCI(pc));
5308 pcn = findFunction(dest);
5310 pct2(of,pcn->pb,indent+1);
5312 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5320 /*-----------------------------------------------------------------*/
5321 /* printCallTree - writes the call tree to a file */
5323 /*-----------------------------------------------------------------*/
5325 void printCallTree(FILE *of)
5337 fprintf(of, "\npBlock statistics\n");
5338 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5343 fprintf(of,"Call Tree\n");
5344 pbr = the_pFile->functions;
5348 if(!ispCodeFunction(pc))
5349 fprintf(of,"bug in call tree");
5352 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5354 while(pc->next && !ispCodeFunction(pc->next)) {
5356 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5357 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5365 fprintf(of,"\n**************\n\na better call tree\n");
5366 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5371 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5372 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5378 /*-----------------------------------------------------------------*/
5380 /*-----------------------------------------------------------------*/
5382 void InlineFunction(pBlock *pb)
5390 pc = setFirstItem(pb->function_calls);
5392 for( ; pc; pc = setNextItem(pb->function_calls)) {
5395 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5401 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5403 //fprintf(stderr,"Cool can inline:\n");
5404 //pcn->print(stderr,pcn);
5406 //fprintf(stderr,"recursive call Inline\n");
5407 InlineFunction(pcn->pb);
5408 //fprintf(stderr,"return from recursive call Inline\n");
5411 At this point, *pc points to a CALL mnemonic, and
5412 *pcn points to the function that is being called.
5414 To in-line this call, we need to remove the CALL
5415 and RETURN(s), and link the function pCode in with
5421 /* Remove the CALL */
5425 /* remove callee pBlock from the pBlock linked list */
5426 removepBlock(pcn->pb);
5434 /* Remove the Function pCode */
5435 pct = findNextInstruction(pcn->next);
5437 /* Link the function with the callee */
5438 pc->next = pcn->next;
5439 pcn->next->prev = pc;
5441 /* Convert the function name into a label */
5443 pbr = Safe_calloc(1,sizeof(pBranch));
5444 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5446 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5447 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5449 /* turn all of the return's except the last into goto's */
5450 /* check case for 2 instruction pBlocks */
5451 pce = findNextInstruction(pcn->next);
5453 pCode *pce_next = findNextInstruction(pce->next);
5455 if(pce_next == NULL) {
5456 /* found the last return */
5457 pCode *pc_call_next = findNextInstruction(pc_call->next);
5459 //fprintf(stderr,"found last return\n");
5460 //pce->print(stderr,pce);
5461 pce->prev->next = pc_call->next;
5462 pc_call->next->prev = pce->prev;
5463 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5473 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5479 /*-----------------------------------------------------------------*/
5481 /*-----------------------------------------------------------------*/
5483 void InlinepCode(void)
5492 if(!functionInlining)
5495 /* Loop through all of the function definitions and count the
5496 * number of times each one is called */
5497 //fprintf(stderr,"inlining %d\n",__LINE__);
5499 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5501 pc = setFirstItem(pb->function_calls);
5503 for( ; pc; pc = setNextItem(pb->function_calls)) {
5506 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5507 if(pcn && isPCF(pcn)) {
5508 PCF(pcn)->ncalled++;
5511 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5516 //fprintf(stderr,"inlining %d\n",__LINE__);
5518 /* Now, Loop through the function definitions again, but this
5519 * time inline those functions that have only been called once. */
5521 InlineFunction(the_pFile->pbHead);
5522 //fprintf(stderr,"inlining %d\n",__LINE__);
5524 for(pb = the_pFile->pbHead; pb; pb = pb->next)