1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
78 int debug_verbose = 1; /* Set true to inundate .asm file */
80 // static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
87 extern int picIsInitialized(void);
89 /****************************************************************/
90 /* Forward declarations */
91 /****************************************************************/
93 void unlinkpCode(pCode *pc);
95 static void genericAnalyze(pCode *pc);
96 static void AnalyzeGOTO(pCode *pc);
97 static void AnalyzeSKIP(pCode *pc);
98 static void AnalyzeRETURN(pCode *pc);
101 static void genericDestruct(pCode *pc);
102 static void genericPrint(FILE *of,pCode *pc);
104 static void pCodePrintLabel(FILE *of, pCode *pc);
105 static void pCodePrintFunction(FILE *of, pCode *pc);
106 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
107 static char *get_op_from_instruction( pCodeInstruction *pcc);
108 char *get_op( pCodeOp *pcop,char *buff,size_t 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
139 0, // literal operand
141 (PCC_W | PCC_REGISTER), // inCond
142 (PCC_REGISTER | PCC_Z) // outCond
145 pCodeInstruction pciADDFW = {
146 {PC_OPCODE, NULL, NULL, 0, NULL,
159 0,0, // dest, bit instruction
161 0, // literal operand
163 (PCC_W | PCC_REGISTER), // inCond
164 (PCC_W | PCC_Z) // outCond
167 pCodeInstruction pciADDLW = {
168 {PC_OPCODE, NULL, NULL, 0, NULL,
181 0,0, // dest, bit instruction
183 1, // literal operand
185 (PCC_W | PCC_LITERAL), // inCond
186 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
189 pCodeInstruction pciANDLW = {
190 {PC_OPCODE, NULL, NULL, 0, NULL,
203 0,0, // dest, bit instruction
205 1, // literal operand
207 (PCC_W | PCC_LITERAL), // inCond
208 (PCC_W | PCC_Z) // outCond
211 pCodeInstruction pciANDWF = {
212 {PC_OPCODE, NULL, NULL, 0, NULL,
225 1,0, // dest, bit instruction
227 0, // literal operand
229 (PCC_W | PCC_REGISTER), // inCond
230 (PCC_REGISTER | PCC_Z) // outCond
233 pCodeInstruction pciANDFW = {
234 {PC_OPCODE, NULL, NULL, 0, NULL,
247 0,0, // dest, bit instruction
249 0, // literal operand
251 (PCC_W | PCC_REGISTER), // inCond
252 (PCC_W | PCC_Z) // outCond
255 pCodeInstruction pciBCF = {
256 {PC_OPCODE, NULL, NULL, 0, NULL,
269 1,1, // dest, bit instruction
271 0, // literal operand
273 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
274 PCC_REGISTER // outCond
277 pCodeInstruction pciBSF = {
278 {PC_OPCODE, NULL, NULL, 0, NULL,
291 1,1, // dest, bit instruction
293 0, // literal operand
295 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
296 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
299 pCodeInstruction pciBTFSC = {
300 {PC_OPCODE, NULL, NULL, 0, NULL,
313 0,1, // dest, bit instruction
315 0, // literal operand
317 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
318 PCC_EXAMINE_PCOP // outCond
321 pCodeInstruction pciBTFSS = {
322 {PC_OPCODE, NULL, NULL, 0, NULL,
335 0,1, // dest, bit instruction
337 0, // literal operand
339 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
340 PCC_EXAMINE_PCOP // outCond
343 pCodeInstruction pciCALL = {
344 {PC_OPCODE, NULL, NULL, 0, NULL,
357 0,0, // dest, bit instruction
359 0, // literal operand
365 pCodeInstruction pciCOMF = {
366 {PC_OPCODE, NULL, NULL, 0, NULL,
379 1,0, // dest, bit instruction
381 0, // literal operand
383 PCC_REGISTER, // inCond
384 PCC_REGISTER // outCond
387 pCodeInstruction pciCOMFW = {
388 {PC_OPCODE, NULL, NULL, 0, NULL,
401 0,0, // dest, bit instruction
403 0, // literal operand
405 PCC_REGISTER, // inCond
409 pCodeInstruction pciCLRF = {
410 {PC_OPCODE, NULL, NULL, 0, NULL,
423 0,0, // dest, bit instruction
425 0, // literal operand
428 PCC_REGISTER // outCond
431 pCodeInstruction pciCLRW = {
432 {PC_OPCODE, NULL, NULL, 0, NULL,
445 0,0, // dest, bit instruction
447 0, // literal operand
453 pCodeInstruction pciCLRWDT = {
454 {PC_OPCODE, NULL, NULL, 0, NULL,
467 0,0, // dest, bit instruction
469 0, // literal operand
475 pCodeInstruction pciDECF = {
476 {PC_OPCODE, NULL, NULL, 0, NULL,
489 1,0, // dest, bit instruction
491 0, // literal operand
493 PCC_REGISTER, // inCond
494 PCC_REGISTER // outCond
497 pCodeInstruction pciDECFW = {
498 {PC_OPCODE, NULL, NULL, 0, NULL,
511 0,0, // dest, bit instruction
513 0, // literal operand
515 PCC_REGISTER, // inCond
519 pCodeInstruction pciDECFSZ = {
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 1,0, // dest, bit instruction
535 0, // literal operand
537 PCC_REGISTER, // inCond
538 PCC_REGISTER // outCond
541 pCodeInstruction pciDECFSZW = {
542 {PC_OPCODE, NULL, NULL, 0, NULL,
555 0,0, // dest, bit instruction
557 0, // literal operand
559 PCC_REGISTER, // inCond
563 pCodeInstruction pciGOTO = {
564 {PC_OPCODE, NULL, NULL, 0, NULL,
577 0,0, // dest, bit instruction
579 0, // literal operand
585 pCodeInstruction pciINCF = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 1,0, // dest, bit instruction
601 0, // literal operand
603 PCC_REGISTER, // inCond
604 PCC_REGISTER // outCond
607 pCodeInstruction pciINCFW = {
608 {PC_OPCODE, NULL, NULL, 0, NULL,
621 0,0, // dest, bit instruction
623 0, // literal operand
625 PCC_REGISTER, // inCond
629 pCodeInstruction pciINCFSZ = {
630 {PC_OPCODE, NULL, NULL, 0, NULL,
643 1,0, // dest, bit instruction
645 0, // literal operand
647 PCC_REGISTER, // inCond
648 PCC_REGISTER // outCond
651 pCodeInstruction pciINCFSZW = {
652 {PC_OPCODE, NULL, NULL, 0, NULL,
665 0,0, // dest, bit instruction
667 0, // literal operand
669 PCC_REGISTER, // inCond
673 pCodeInstruction pciIORWF = {
674 {PC_OPCODE, NULL, NULL, 0, NULL,
687 1,0, // dest, bit instruction
689 0, // literal operand
691 (PCC_W | PCC_REGISTER), // inCond
692 (PCC_REGISTER | PCC_Z) // outCond
695 pCodeInstruction pciIORFW = {
696 {PC_OPCODE, NULL, NULL, 0, NULL,
709 0,0, // dest, bit instruction
711 0, // literal operand
713 (PCC_W | PCC_REGISTER), // inCond
714 (PCC_W | PCC_Z) // outCond
717 pCodeInstruction pciIORLW = {
718 {PC_OPCODE, NULL, NULL, 0, NULL,
731 0,0, // dest, bit instruction
733 1, // literal operand
735 (PCC_W | PCC_LITERAL), // inCond
736 (PCC_W | PCC_Z) // outCond
739 pCodeInstruction pciMOVF = {
740 {PC_OPCODE, NULL, NULL, 0, NULL,
753 1,0, // dest, bit instruction
755 0, // literal operand
757 PCC_REGISTER, // inCond
761 pCodeInstruction pciMOVFW = {
762 {PC_OPCODE, NULL, NULL, 0, NULL,
775 0,0, // dest, bit instruction
777 0, // literal operand
779 PCC_REGISTER, // inCond
780 (PCC_W | PCC_Z) // outCond
783 pCodeInstruction pciMOVWF = {
784 {PC_OPCODE, NULL, NULL, 0, NULL,
797 0,0, // dest, bit instruction
799 0, // literal operand
802 PCC_REGISTER // outCond
805 pCodeInstruction pciMOVLW = {
806 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 1, // literal operand
822 (PCC_NONE | PCC_LITERAL), // inCond
826 pCodeInstruction pciNOP = {
827 {PC_OPCODE, NULL, NULL, 0, NULL,
839 0,0, // dest, bit instruction
841 0, // literal operand
847 pCodeInstruction pciRETFIE = {
848 {PC_OPCODE, NULL, NULL, 0, NULL,
861 0,0, // dest, bit instruction
863 0, // literal operand
866 PCC_NONE // outCond (not true... affects the GIE bit too)
869 pCodeInstruction pciRETLW = {
870 {PC_OPCODE, NULL, NULL, 0, NULL,
883 0,0, // dest, bit instruction
885 1, // literal operand
887 PCC_LITERAL, // inCond
891 pCodeInstruction pciRETURN = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
905 0,0, // dest, bit instruction
907 0, // literal operand
913 pCodeInstruction pciRLF = {
914 {PC_OPCODE, NULL, NULL, 0, NULL,
927 1,0, // dest, bit instruction
929 0, // literal operand
931 (PCC_C | PCC_REGISTER), // inCond
932 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
935 pCodeInstruction pciRLFW = {
936 {PC_OPCODE, NULL, NULL, 0, NULL,
949 0,0, // dest, bit instruction
951 0, // literal operand
953 (PCC_C | PCC_REGISTER), // inCond
954 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
957 pCodeInstruction pciRRF = {
958 {PC_OPCODE, NULL, NULL, 0, NULL,
971 1,0, // dest, bit instruction
973 0, // literal operand
975 (PCC_C | PCC_REGISTER), // inCond
976 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
979 pCodeInstruction pciRRFW = {
980 {PC_OPCODE, NULL, NULL, 0, NULL,
993 0,0, // dest, bit instruction
995 0, // literal operand
997 (PCC_C | PCC_REGISTER), // inCond
998 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1001 pCodeInstruction pciSUBWF = {
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1008 NULL, // from branch
1015 1,0, // dest, bit instruction
1016 0,0, // branch, skip
1017 0, // literal operand
1019 (PCC_W | PCC_REGISTER), // inCond
1020 (PCC_REGISTER | PCC_Z) // outCond
1023 pCodeInstruction pciSUBFW = {
1024 {PC_OPCODE, NULL, NULL, 0, NULL,
1030 NULL, // from branch
1037 0,0, // dest, bit instruction
1038 0,0, // branch, skip
1039 0, // literal operand
1041 (PCC_W | PCC_REGISTER), // inCond
1042 (PCC_W | PCC_Z) // outCond
1045 pCodeInstruction pciSUBLW = {
1046 {PC_OPCODE, NULL, NULL, 0, NULL,
1052 NULL, // from branch
1059 0,0, // dest, bit instruction
1060 0,0, // branch, skip
1061 1, // literal operand
1063 (PCC_W | PCC_LITERAL), // inCond
1064 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1067 pCodeInstruction pciSWAPF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1085 (PCC_REGISTER), // inCond
1086 (PCC_REGISTER) // outCond
1089 pCodeInstruction pciSWAPFW = {
1090 {PC_OPCODE, NULL, NULL, 0, NULL,
1096 NULL, // from branch
1103 0,0, // dest, bit instruction
1104 0,0, // branch, skip
1105 0, // literal operand
1107 (PCC_REGISTER), // inCond
1111 pCodeInstruction pciTRIS = {
1112 {PC_OPCODE, NULL, NULL, 0, NULL,
1118 NULL, // from branch
1125 0,0, // dest, bit instruction
1126 0,0, // branch, skip
1127 0, // literal operand
1130 PCC_REGISTER // outCond
1133 pCodeInstruction pciXORWF = {
1134 {PC_OPCODE, NULL, NULL, 0, NULL,
1140 NULL, // from branch
1147 1,0, // dest, bit instruction
1148 0,0, // branch, skip
1149 0, // literal operand
1151 (PCC_W | PCC_REGISTER), // inCond
1152 (PCC_REGISTER | PCC_Z) // outCond
1155 pCodeInstruction pciXORFW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1162 NULL, // from branch
1169 0,0, // dest, bit instruction
1170 0,0, // branch, skip
1171 0, // literal operand
1173 (PCC_W | PCC_REGISTER), // inCond
1174 (PCC_W | PCC_Z) // outCond
1177 pCodeInstruction pciXORLW = {
1178 {PC_OPCODE, NULL, NULL, 0, NULL,
1184 NULL, // from branch
1191 0,0, // dest, bit instruction
1192 0,0, // branch, skip
1193 1, // literal operand
1195 (PCC_W | PCC_LITERAL), // inCond
1196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1200 #define MAX_PIC14MNEMONICS 100
1201 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1204 #ifdef HAVE_VSNPRINTF
1205 // Alas, vsnprintf is not ANSI standard, and does not exist
1206 // on Solaris (and probably other non-Gnu flavored Unixes).
1208 /*-----------------------------------------------------------------*/
1209 /* SAFE_snprintf - like snprintf except the string pointer is */
1210 /* after the string has been printed to. This is */
1211 /* useful for printing to string as though if it */
1212 /* were a stream. */
1213 /*-----------------------------------------------------------------*/
1214 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1222 va_start(val, format);
1224 vsnprintf(*str, *size, format, val);
1230 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1231 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1239 #else // HAVE_VSNPRINTF
1241 // This version is *not* safe, despite the name.
1243 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1247 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1252 va_start(val, format);
1254 vsprintf(buffer, format, val);
1257 len = strlen(buffer);
1259 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1260 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1263 strcpy(*str, buffer);
1269 #endif // HAVE_VSNPRINTF
1272 extern void initStack(int base_address, int size);
1273 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1274 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1275 extern void init_pic(char *);
1277 void pCodeInitRegisters(void)
1279 static int initialized=0;
1285 initStack(0xfff, 8);
1286 init_pic(port->processor);
1288 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1289 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1290 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1291 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1292 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1293 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1295 pc_status.rIdx = IDX_STATUS;
1296 pc_fsr.rIdx = IDX_FSR;
1297 pc_indf.rIdx = IDX_INDF;
1298 pc_intcon.rIdx = IDX_INTCON;
1299 pc_pcl.rIdx = IDX_PCL;
1300 pc_pclath.rIdx = IDX_PCLATH;
1302 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1303 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1304 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1306 pc_kzero.rIdx = IDX_KZ;
1307 pc_wsave.rIdx = IDX_WSAVE;
1308 pc_ssave.rIdx = IDX_SSAVE;
1310 /* probably should put this in a separate initialization routine */
1311 pb_dead_pcodes = newpBlock();
1315 /*-----------------------------------------------------------------*/
1316 /* mnem2key - convert a pic mnemonic into a hash key */
1317 /* (BTW - this spreads the mnemonics quite well) */
1319 /*-----------------------------------------------------------------*/
1321 int mnem2key(char const *mnem)
1330 key += toupper(*mnem++) +1;
1334 return (key & 0x1f);
1338 void pic14initMnemonics(void)
1343 pCodeInstruction *pci;
1345 if(mnemonics_initialized)
1348 //FIXME - probably should NULL out the array before making the assignments
1349 //since we check the array contents below this initialization.
1351 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1352 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1353 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1354 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1355 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1356 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1357 pic14Mnemonics[POC_BCF] = &pciBCF;
1358 pic14Mnemonics[POC_BSF] = &pciBSF;
1359 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1360 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1361 pic14Mnemonics[POC_CALL] = &pciCALL;
1362 pic14Mnemonics[POC_COMF] = &pciCOMF;
1363 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1364 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1365 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1366 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1367 pic14Mnemonics[POC_DECF] = &pciDECF;
1368 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1369 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1370 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1371 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1372 pic14Mnemonics[POC_INCF] = &pciINCF;
1373 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1374 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1375 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1376 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1377 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1378 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1379 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1380 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1381 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1382 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1383 pic14Mnemonics[POC_NOP] = &pciNOP;
1384 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1385 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1386 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1387 pic14Mnemonics[POC_RLF] = &pciRLF;
1388 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1389 pic14Mnemonics[POC_RRF] = &pciRRF;
1390 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1391 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1392 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1393 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1394 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1395 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1396 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1397 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1398 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1399 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1401 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1402 if(pic14Mnemonics[i])
1403 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1404 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1407 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1408 pci = hTabNextItem(pic14MnemonicsHash, &key);
1411 mnemonics_initialized = 1;
1414 int getpCodePeepCommand(char *cmd);
1416 int getpCode(char *mnem,unsigned dest)
1419 pCodeInstruction *pci;
1420 int key = mnem2key(mnem);
1422 if(!mnemonics_initialized)
1423 pic14initMnemonics();
1425 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1429 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1430 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1434 pci = hTabNextItemWK (pic14MnemonicsHash);
1441 /*-----------------------------------------------------------------*
1442 * pic14initpCodePeepCommands
1444 *-----------------------------------------------------------------*/
1445 void pic14initpCodePeepCommands(void)
1453 hTabAddItem(&pic14pCodePeepCommandsHash,
1454 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1456 } while (peepCommands[i].cmd);
1458 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1461 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1462 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1467 /*-----------------------------------------------------------------
1470 *-----------------------------------------------------------------*/
1472 int getpCodePeepCommand(char *cmd)
1476 int key = mnem2key(cmd);
1479 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1482 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1483 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1487 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1494 char getpBlock_dbName(pBlock *pb)
1500 return pb->cmemmap->dbName;
1504 void pBlockConvert2ISR(pBlock *pb)
1515 /*-----------------------------------------------------------------*/
1516 /* movepBlock2Head - given the dbname of a pBlock, move all */
1517 /* instances to the front of the doubly linked */
1518 /* list of pBlocks */
1519 /*-----------------------------------------------------------------*/
1521 void movepBlock2Head(char dbName)
1525 pb = the_pFile->pbHead;
1529 if(getpBlock_dbName(pb) == dbName) {
1530 pBlock *pbn = pb->next;
1531 pb->next = the_pFile->pbHead;
1532 the_pFile->pbHead->prev = pb;
1533 the_pFile->pbHead = pb;
1536 pb->prev->next = pbn;
1538 // If the pBlock that we just moved was the last
1539 // one in the link of all of the pBlocks, then we
1540 // need to point the tail to the block just before
1541 // the one we moved.
1542 // Note: if pb->next is NULL, then pb must have
1543 // been the last pBlock in the chain.
1546 pbn->prev = pb->prev;
1548 the_pFile->pbTail = pb->prev;
1559 void copypCode(FILE *of, char dbName)
1563 if(!of || !the_pFile)
1566 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1567 if(getpBlock_dbName(pb) == dbName) {
1574 void pcode_test(void)
1577 DFPRINTF((stderr,"pcode is alive!\n"));
1587 /* create the file name */
1588 strcpy(buffer,dstFileName);
1589 strcat(buffer,".p");
1591 if( !(pFile = fopen(buffer, "w" ))) {
1592 werror(E_FILE_OPEN_ERR,buffer);
1596 fprintf(pFile,"pcode dump\n\n");
1598 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1599 fprintf(pFile,"\n\tNew pBlock\n\n");
1601 fprintf(pFile,"%s",pb->cmemmap->sname);
1603 fprintf(pFile,"internal pblock");
1605 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1606 printpBlock(pFile,pb);
1610 /*-----------------------------------------------------------------*/
1611 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1612 /* ister, RegCond will return the bit being referenced. */
1614 /* fixme - why not just OR in the pcop bit field */
1615 /*-----------------------------------------------------------------*/
1617 static int RegCond(pCodeOp *pcop)
1623 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1624 switch(PCORB(pcop)->bit) {
1638 /*-----------------------------------------------------------------*/
1639 /* newpCode - create and return a newly initialized pCode */
1641 /* fixme - rename this */
1643 /* The purpose of this routine is to create a new Instruction */
1644 /* pCode. This is called by gen.c while the assembly code is being */
1648 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1649 /* (note that the op is analogous to but not the */
1650 /* same thing as the opcode of the instruction.) */
1651 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1654 /* a pointer to the new malloc'd pCode is returned. */
1658 /*-----------------------------------------------------------------*/
1659 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1661 pCodeInstruction *pci ;
1663 if(!mnemonics_initialized)
1664 pic14initMnemonics();
1666 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1668 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1669 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1672 if(pci->inCond & PCC_EXAMINE_PCOP)
1673 pci->inCond |= RegCond(pcop);
1675 if(pci->outCond & PCC_EXAMINE_PCOP)
1676 pci->outCond |= RegCond(pcop);
1678 pci->pc.prev = pci->pc.next = NULL;
1679 return (pCode *)pci;
1682 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1688 /*-----------------------------------------------------------------*/
1689 /* newpCodeWild - create a "wild" as in wild card pCode */
1691 /* Wild pcodes are used during the peep hole optimizer to serve */
1692 /* as place holders for any instruction. When a snippet of code is */
1693 /* compared to a peep hole rule, the wild card opcode will match */
1694 /* any instruction. However, the optional operand and label are */
1695 /* additional qualifiers that must also be matched before the */
1696 /* line (of assembly code) is declared matched. Note that the */
1697 /* operand may be wild too. */
1699 /* Note, a wild instruction is specified just like a wild var: */
1700 /* %4 ; A wild instruction, */
1701 /* See the peeph.def file for additional examples */
1703 /*-----------------------------------------------------------------*/
1705 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1710 pcw = Safe_calloc(1,sizeof(pCodeWild));
1712 pcw->pci.pc.type = PC_WILD;
1713 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1714 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1715 pcw->pci.pc.pb = NULL;
1717 // pcw->pci.pc.analyze = genericAnalyze;
1718 pcw->pci.pc.destruct = genericDestruct;
1719 pcw->pci.pc.print = genericPrint;
1721 pcw->id = pCodeID; // this is the 'n' in %n
1722 pcw->operand = optional_operand;
1723 pcw->label = optional_label;
1725 pcw->mustBeBitSkipInst = 0;
1726 pcw->mustNotBeBitSkipInst = 0;
1727 pcw->invertBitSkipInst = 0;
1729 return ( (pCode *)pcw);
1733 /*-----------------------------------------------------------------*/
1734 /* newPcodeInlineP - create a new pCode from a char string */
1735 /*-----------------------------------------------------------------*/
1738 pCode *newpCodeInlineP(char *cP)
1743 pcc = Safe_calloc(1,sizeof(pCodeComment));
1745 pcc->pc.type = PC_INLINE;
1746 pcc->pc.prev = pcc->pc.next = NULL;
1747 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1750 // pcc->pc.analyze = genericAnalyze;
1751 pcc->pc.destruct = genericDestruct;
1752 pcc->pc.print = genericPrint;
1755 pcc->comment = Safe_strdup(cP);
1757 pcc->comment = NULL;
1759 return ( (pCode *)pcc);
1763 /*-----------------------------------------------------------------*/
1764 /* newPcodeCharP - create a new pCode from a char string */
1765 /*-----------------------------------------------------------------*/
1767 pCode *newpCodeCharP(char *cP)
1772 pcc = Safe_calloc(1,sizeof(pCodeComment));
1774 pcc->pc.type = PC_COMMENT;
1775 pcc->pc.prev = pcc->pc.next = NULL;
1776 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1779 // pcc->pc.analyze = genericAnalyze;
1780 pcc->pc.destruct = genericDestruct;
1781 pcc->pc.print = genericPrint;
1784 pcc->comment = Safe_strdup(cP);
1786 pcc->comment = NULL;
1788 return ( (pCode *)pcc);
1792 /*-----------------------------------------------------------------*/
1793 /* newpCodeFunction - */
1794 /*-----------------------------------------------------------------*/
1797 pCode *newpCodeFunction(char *mod,char *f)
1801 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1802 //_ALLOC(pcf,sizeof(pCodeFunction));
1804 pcf->pc.type = PC_FUNCTION;
1805 pcf->pc.prev = pcf->pc.next = NULL;
1806 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1809 // pcf->pc.analyze = genericAnalyze;
1810 pcf->pc.destruct = genericDestruct;
1811 pcf->pc.print = pCodePrintFunction;
1816 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1817 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1818 strcpy(pcf->modname,mod);
1820 pcf->modname = NULL;
1823 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1824 pcf->fname = Safe_calloc(1,strlen(f)+1);
1825 strcpy(pcf->fname,f);
1829 return ( (pCode *)pcf);
1833 /*-----------------------------------------------------------------*/
1835 /*-----------------------------------------------------------------*/
1836 void destructpCodeFlow(pCode *pc)
1838 if(!pc || !isPCFL(pc))
1847 deleteSet(&PCFL(pc)->registers);
1848 deleteSet(&PCFL(pc)->from);
1849 deleteSet(&PCFL(pc)->to);
1854 pCode *newpCodeFlow(void )
1858 //_ALLOC(pcflow,sizeof(pCodeFlow));
1859 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1861 pcflow->pc.type = PC_FLOW;
1862 pcflow->pc.prev = pcflow->pc.next = NULL;
1863 pcflow->pc.pb = NULL;
1865 // pcflow->pc.analyze = genericAnalyze;
1866 pcflow->pc.destruct = destructpCodeFlow;
1867 pcflow->pc.print = genericPrint;
1869 pcflow->pc.seq = GpcFlowSeq++;
1871 pcflow->from = pcflow->to = NULL;
1873 pcflow->inCond = PCC_NONE;
1874 pcflow->outCond = PCC_NONE;
1876 pcflow->firstBank = -1;
1877 pcflow->lastBank = -1;
1879 pcflow->FromConflicts = 0;
1880 pcflow->ToConflicts = 0;
1884 pcflow->registers = newSet();
1886 return ( (pCode *)pcflow);
1890 /*-----------------------------------------------------------------*/
1891 /*-----------------------------------------------------------------*/
1892 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1894 pCodeFlowLink *pcflowLink;
1896 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1898 pcflowLink->pcflow = pcflow;
1899 pcflowLink->bank_conflict = 0;
1904 /*-----------------------------------------------------------------*/
1905 /* newpCodeCSource - create a new pCode Source Symbol */
1906 /*-----------------------------------------------------------------*/
1908 pCode *newpCodeCSource(int ln, char *f, char *l)
1913 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1915 pccs->pc.type = PC_CSOURCE;
1916 pccs->pc.prev = pccs->pc.next = NULL;
1919 pccs->pc.destruct = genericDestruct;
1920 pccs->pc.print = genericPrint;
1922 pccs->line_number = ln;
1924 pccs->line = Safe_strdup(l);
1929 pccs->file_name = Safe_strdup(f);
1931 pccs->file_name = NULL;
1933 return ( (pCode *)pccs);
1936 /*-----------------------------------------------------------------*/
1937 /* pCodeLabelDestruct - free memory used by a label. */
1938 /*-----------------------------------------------------------------*/
1939 static void pCodeLabelDestruct(pCode *pc)
1945 if((pc->type == PC_LABEL) && PCL(pc)->label)
1946 free(PCL(pc)->label);
1952 pCode *newpCodeLabel(char *name, int key)
1958 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1960 pcl->pc.type = PC_LABEL;
1961 pcl->pc.prev = pcl->pc.next = NULL;
1962 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1965 // pcl->pc.analyze = genericAnalyze;
1966 pcl->pc.destruct = pCodeLabelDestruct;
1967 pcl->pc.print = pCodePrintLabel;
1973 sprintf(s,"_%05d_DS_",key);
1978 pcl->label = Safe_strdup(s);
1980 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1981 return ( (pCode *)pcl);
1986 /*-----------------------------------------------------------------*/
1987 /* newpBlock - create and return a pointer to a new pBlock */
1988 /*-----------------------------------------------------------------*/
1989 pBlock *newpBlock(void)
1994 PpB = Safe_calloc(1,sizeof(pBlock) );
1995 PpB->next = PpB->prev = NULL;
1997 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1998 PpB->tregisters = NULL;
2000 PpB->FlowTree = NULL;
2006 /*-----------------------------------------------------------------*/
2007 /* newpCodeChain - create a new chain of pCodes */
2008 /*-----------------------------------------------------------------*
2010 * This function will create a new pBlock and the pointer to the
2011 * pCode that is passed in will be the first pCode in the block.
2012 *-----------------------------------------------------------------*/
2015 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2018 pBlock *pB = newpBlock();
2020 pB->pcHead = pB->pcTail = pc;
2027 /*-----------------------------------------------------------------*/
2028 /* newpCodeOpLabel - Create a new label given the key */
2029 /* Note, a negative key means that the label is part of wild card */
2030 /* (and hence a wild card label) used in the pCodePeep */
2031 /* optimizations). */
2032 /*-----------------------------------------------------------------*/
2034 pCodeOp *newpCodeOpLabel(char *name, int key)
2037 static int label_key=-1;
2041 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2042 pcop->type = PO_LABEL;
2047 sprintf(s=buffer,"_%05d_DS_",key);
2049 s = name, key = label_key--;
2052 pcop->name = Safe_strdup(s);
2054 ((pCodeOpLabel *)pcop)->key = key;
2056 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2060 /*-----------------------------------------------------------------*/
2061 /*-----------------------------------------------------------------*/
2062 pCodeOp *newpCodeOpLit(int lit)
2068 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2069 pcop->type = PO_LITERAL;
2073 sprintf(s,"0x%02x",lit);
2075 pcop->name = Safe_strdup(s);
2078 ((pCodeOpLit *)pcop)->lit = lit;
2083 /*-----------------------------------------------------------------*/
2084 /*-----------------------------------------------------------------*/
2085 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2089 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2090 pcop->type = PO_IMMEDIATE;
2092 regs *r = dirregWithName(name);
2093 pcop->name = Safe_strdup(name);
2096 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2097 PCOI(pcop)->rIdx = r->rIdx;
2099 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2100 PCOI(pcop)->rIdx = -1;
2102 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2107 PCOI(pcop)->index = index;
2108 PCOI(pcop)->offset = offset;
2109 PCOI(pcop)->_const = code_space;
2114 /*-----------------------------------------------------------------*/
2115 /*-----------------------------------------------------------------*/
2116 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2122 if(!pcwb || !subtype) {
2123 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2127 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2128 pcop->type = PO_WILD;
2129 sprintf(s,"%%%d",id);
2130 pcop->name = Safe_strdup(s);
2132 PCOW(pcop)->id = id;
2133 PCOW(pcop)->pcwb = pcwb;
2134 PCOW(pcop)->subtype = subtype;
2135 PCOW(pcop)->matched = NULL;
2140 /*-----------------------------------------------------------------*/
2141 /*-----------------------------------------------------------------*/
2142 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2146 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2147 pcop->type = PO_GPR_BIT;
2149 pcop->name = Safe_strdup(s);
2153 PCORB(pcop)->bit = bit;
2154 PCORB(pcop)->inBitSpace = inBitSpace;
2156 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2157 PCOR(pcop)->r = NULL;
2158 PCOR(pcop)->rIdx = 0;
2162 /*-----------------------------------------------------------------*
2163 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2165 * If rIdx >=0 then a specific register from the set of registers
2166 * will be selected. If rIdx <0, then a new register will be searched
2168 *-----------------------------------------------------------------*/
2170 pCodeOp *newpCodeOpReg(int rIdx)
2174 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2179 PCOR(pcop)->rIdx = rIdx;
2180 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2182 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2185 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2188 pcop->type = PCOR(pcop)->r->pc_type;
2193 pCodeOp *newpCodeOpRegFromStr(char *name)
2197 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2198 PCOR(pcop)->r = allocRegByName(name, 1);
2199 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2200 pcop->type = PCOR(pcop)->r->pc_type;
2201 pcop->name = PCOR(pcop)->r->name;
2206 /*-----------------------------------------------------------------*/
2207 /*-----------------------------------------------------------------*/
2209 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2216 pcop = newpCodeOpBit(name, -1,0);
2220 pcop = newpCodeOpLit(-1);
2224 pcop = newpCodeOpLabel(NULL,-1);
2227 pcop = newpCodeOpReg(-1);
2230 case PO_GPR_REGISTER:
2232 pcop = newpCodeOpRegFromStr(name);
2234 pcop = newpCodeOpReg(-1);
2238 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2241 pcop->name = Safe_strdup(name);
2249 /*-----------------------------------------------------------------*/
2250 /*-----------------------------------------------------------------*/
2251 void pCodeConstString(char *name, char *value)
2255 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2260 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2264 sprintf(buffer,"; %s = %s",name,value);
2266 addpCode2pBlock(pb,newpCodeCharP(buffer));
2267 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2270 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2276 /*-----------------------------------------------------------------*/
2277 /*-----------------------------------------------------------------*/
2278 void pCodeReadCodeTable(void)
2282 fprintf(stderr, " %s\n",__FUNCTION__);
2284 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2288 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2289 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2290 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2291 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2293 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2294 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2295 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2296 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2301 /*-----------------------------------------------------------------*/
2302 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2303 /*-----------------------------------------------------------------*/
2304 void addpCode2pBlock(pBlock *pb, pCode *pc)
2311 /* If this is the first pcode to be added to a block that
2312 * was initialized with a NULL pcode, then go ahead and
2313 * make this pcode the head and tail */
2314 pb->pcHead = pb->pcTail = pc;
2317 pb->pcTail->next = pc;
2319 pc->prev = pb->pcTail;
2326 /*-----------------------------------------------------------------*/
2327 /* addpBlock - place a pBlock into the pFile */
2328 /*-----------------------------------------------------------------*/
2329 void addpBlock(pBlock *pb)
2331 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2334 /* First time called, we'll pass through here. */
2335 //_ALLOC(the_pFile,sizeof(pFile));
2336 the_pFile = Safe_calloc(1,sizeof(pFile));
2337 the_pFile->pbHead = the_pFile->pbTail = pb;
2338 the_pFile->functions = NULL;
2342 the_pFile->pbTail->next = pb;
2343 pb->prev = the_pFile->pbTail;
2345 the_pFile->pbTail = pb;
2348 /*-----------------------------------------------------------------*/
2349 /* removepBlock - remove a pBlock from the pFile */
2350 /*-----------------------------------------------------------------*/
2351 void removepBlock(pBlock *pb)
2359 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2361 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2364 if(pbs == the_pFile->pbHead)
2365 the_pFile->pbHead = pbs->next;
2367 if (pbs == the_pFile->pbTail)
2368 the_pFile->pbTail = pbs->prev;
2371 pbs->next->prev = pbs->prev;
2374 pbs->prev->next = pbs->next;
2381 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2385 /*-----------------------------------------------------------------*/
2386 /* printpCode - write the contents of a pCode to a file */
2387 /*-----------------------------------------------------------------*/
2388 void printpCode(FILE *of, pCode *pc)
2399 fprintf(of,"warning - unable to print pCode\n");
2402 /*-----------------------------------------------------------------*/
2403 /* printpBlock - write the contents of a pBlock to a file */
2404 /*-----------------------------------------------------------------*/
2405 void printpBlock(FILE *of, pBlock *pb)
2415 for(pc = pb->pcHead; pc; pc = pc->next)
2420 /*-----------------------------------------------------------------*/
2422 /* pCode processing */
2426 /*-----------------------------------------------------------------*/
2428 void unlinkpCode(pCode *pc)
2434 fprintf(stderr,"Unlinking: ");
2435 printpCode(stderr, pc);
2438 pc->prev->next = pc->next;
2440 pc->next->prev = pc->prev;
2442 pc->prev = pc->next = NULL;
2446 /*-----------------------------------------------------------------*/
2447 /*-----------------------------------------------------------------*/
2449 static void genericDestruct(pCode *pc)
2455 /* For instructions, tell the register (if there's one used)
2456 * that it's no longer needed */
2457 regs *reg = getRegFromInstruction(pc);
2459 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2462 /* Instead of deleting the memory used by this pCode, mark
2463 * the object as bad so that if there's a pointer to this pCode
2464 * dangling around somewhere then (hopefully) when the type is
2465 * checked we'll catch it.
2470 addpCode2pBlock(pb_dead_pcodes, pc);
2477 /*-----------------------------------------------------------------*/
2478 /*-----------------------------------------------------------------*/
2479 void pBlockRegs(FILE *of, pBlock *pb)
2484 r = setFirstItem(pb->tregisters);
2486 r = setNextItem(pb->tregisters);
2491 /*-----------------------------------------------------------------*/
2492 /*-----------------------------------------------------------------*/
2493 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2498 int use_buffer = 1; // copy the string to the passed buffer pointer
2503 use_buffer = 0; // Don't bother copying the string to the buffer.
2507 switch(pcop->type) {
2511 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2514 return PCOR(pcop)->r->name;
2517 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2520 SAFE_snprintf(&buffer,&size,"%s",r->name);
2530 if(PCOI(pcop)->_const) {
2532 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2533 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2536 8 * PCOI(pcop)->offset );
2538 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2541 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2542 SAFE_snprintf(&s,&size,"(%s + %d)",
2544 PCOI(pcop)->index );
2546 if(PCOI(pcop)->offset)
2547 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2549 SAFE_snprintf(&s,&size,"%s",pcop->name);
2557 //size = sizeof(buffer);
2558 if( PCOR(pcop)->instance) {
2559 SAFE_snprintf(&s,&size,"(%s + %d)",
2561 PCOR(pcop)->instance );
2562 //fprintf(stderr,"PO_DIR %s\n",buffer);
2564 SAFE_snprintf(&s,&size,"%s",pcop->name);
2570 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2579 return "NO operand";
2583 /*-----------------------------------------------------------------*/
2584 /*-----------------------------------------------------------------*/
2585 static char *get_op_from_instruction( pCodeInstruction *pcc)
2589 return get_op(pcc->pcop,NULL,0);
2591 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2592 return ("ERROR Null: "__FUNCTION__);
2594 return ("ERROR Null: get_op_from_instruction");
2598 /*-----------------------------------------------------------------*/
2599 /*-----------------------------------------------------------------*/
2600 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2603 fprintf(of,"pcodeopprint- not implemented\n");
2606 /*-----------------------------------------------------------------*/
2607 /*-----------------------------------------------------------------*/
2608 char *pCode2str(char *str, size_t size, pCode *pc)
2616 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2618 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2620 if(PCI(pc)->isBitInst) {
2621 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2622 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2623 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2624 PCI(pc)->pcop->name ,
2625 PCI(pc)->pcop->name );
2627 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2628 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2629 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2630 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2632 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2633 //PCI(pc)->pcop->t.bit );
2636 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2637 if( PCI(pc)->num_ops == 2)
2638 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2640 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2643 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2645 if( PCI(pc)->num_ops == 2)
2646 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2654 /* assuming that comment ends with a \n */
2655 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2659 /* assuming that inline code ends with a \n */
2660 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2664 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2667 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2670 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2673 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2676 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2680 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2687 /*-----------------------------------------------------------------*/
2688 /* genericPrint - the contents of a pCode to a file */
2689 /*-----------------------------------------------------------------*/
2690 static void genericPrint(FILE *of, pCode *pc)
2698 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2702 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2706 // If the opcode has a label, print that first
2708 pBranch *pbl = PCI(pc)->label;
2709 while(pbl && pbl->pc) {
2710 if(pbl->pc->type == PC_LABEL)
2711 pCodePrintLabel(of, pbl->pc);
2717 genericPrint(of,PCODE(PCI(pc)->cline));
2722 pCode2str(str, 256, pc);
2724 fprintf(of,"%s",str);
2728 fprintf(of, "\t;key=%03x",pc->seq);
2730 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2735 pBranch *dpb = pc->to; // debug
2737 switch ( dpb->pc->type) {
2739 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2742 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2745 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2748 fprintf(of, "\t;flow");
2762 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2763 if(PCW(pc)->pci.label)
2764 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2766 if(PCW(pc)->operand) {
2767 fprintf(of,";\toperand ");
2768 pCodeOpPrint(of,PCW(pc)->operand );
2774 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2775 if(PCFL(pc)->ancestor)
2776 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2783 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2787 fprintf(of,"unknown pCode type %d\n",pc->type);
2792 /*-----------------------------------------------------------------*/
2793 /* pCodePrintFunction - prints function begin/end */
2794 /*-----------------------------------------------------------------*/
2796 static void pCodePrintFunction(FILE *of, pCode *pc)
2802 if( ((pCodeFunction *)pc)->modname)
2803 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2805 if(PCF(pc)->fname) {
2806 pBranch *exits = PCF(pc)->to;
2808 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2811 exits = exits->next;
2814 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2817 if((PCF(pc)->from &&
2818 PCF(pc)->from->pc->type == PC_FUNCTION &&
2819 PCF(PCF(pc)->from->pc)->fname) )
2820 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2822 fprintf(of,"; exit point [can't find entry point]\n");
2825 /*-----------------------------------------------------------------*/
2826 /* pCodePrintLabel - prints label */
2827 /*-----------------------------------------------------------------*/
2829 static void pCodePrintLabel(FILE *of, pCode *pc)
2836 fprintf(of,"%s\n",PCL(pc)->label);
2837 else if (PCL(pc)->key >=0)
2838 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2840 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2843 /*-----------------------------------------------------------------*/
2844 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2845 /* remove it if it is found. */
2846 /*-----------------------------------------------------------------*/
2847 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2854 if(pcl->type == PC_OPCODE)
2855 b = PCI(pcl)->label;
2857 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2862 //fprintf (stderr, "%s \n",__FUNCTION__);
2863 //pcl->print(stderr,pcl);
2864 //pc->print(stderr,pc);
2867 //fprintf (stderr, "found label\n");
2871 bprev->next = b->next; /* Not first pCode in chain */
2875 PCI(pcl)->label = b->next; /* First pCode in chain */
2878 return; /* A label can't occur more than once */
2886 /*-----------------------------------------------------------------*/
2887 /*-----------------------------------------------------------------*/
2888 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2907 /*-----------------------------------------------------------------*/
2908 /* pBranchLink - given two pcodes, this function will link them */
2909 /* together through their pBranches */
2910 /*-----------------------------------------------------------------*/
2911 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2915 // Declare a new branch object for the 'from' pCode.
2917 //_ALLOC(b,sizeof(pBranch));
2918 b = Safe_calloc(1,sizeof(pBranch));
2919 b->pc = PCODE(t); // The link to the 'to' pCode.
2922 f->to = pBranchAppend(f->to,b);
2924 // Now do the same for the 'to' pCode.
2926 //_ALLOC(b,sizeof(pBranch));
2927 b = Safe_calloc(1,sizeof(pBranch));
2931 t->from = pBranchAppend(t->from,b);
2936 /*-----------------------------------------------------------------*/
2937 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2939 /*-----------------------------------------------------------------*/
2940 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2953 /*-----------------------------------------------------------------*/
2954 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2955 /*-----------------------------------------------------------------*/
2956 static void pCodeUnlink(pCode *pc)
2961 if(!pc->prev || !pc->next) {
2962 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2966 /* first remove the pCode from the chain */
2967 pc->prev->next = pc->next;
2968 pc->next->prev = pc->prev;
2970 /* Now for the hard part... */
2972 /* Remove the branches */
2976 pc1 = pb1->pc; /* Get the pCode that branches to the
2977 * one we're unlinking */
2979 /* search for the link back to this pCode (the one we're
2981 if(pb2 = pBranchFind(pc1->to,pc)) {
2982 pb2->pc = pc->to->pc; // make the replacement
2984 /* if the pCode we're unlinking contains multiple 'to'
2985 * branches (e.g. this a skip instruction) then we need
2986 * to copy these extra branches to the chain. */
2988 pBranchAppend(pb2, pc->to->next);
2997 /*-----------------------------------------------------------------*/
2998 /*-----------------------------------------------------------------*/
3000 static void genericAnalyze(pCode *pc)
3010 // Go through the pCodes that are in pCode chain and link
3011 // them together through the pBranches. Note, the pCodes
3012 // are linked together as a contiguous stream like the
3013 // assembly source code lines. The linking here mimics this
3014 // except that comments are not linked in.
3016 pCode *npc = pc->next;
3018 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3019 pBranchLink(pc,npc);
3024 /* reached the end of the pcode chain without finding
3025 * an instruction we could link to. */
3029 fprintf(stderr,"analyze PC_FLOW\n");
3033 fprintf(stderr,,";A bad pCode is being used\n");
3039 /*-----------------------------------------------------------------*/
3040 /*-----------------------------------------------------------------*/
3041 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3045 if(pc->type == PC_LABEL) {
3046 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3049 if(pc->type == PC_OPCODE) {
3050 pbr = PCI(pc)->label;
3052 if(pbr->pc->type == PC_LABEL) {
3053 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3063 /*-----------------------------------------------------------------*/
3064 /*-----------------------------------------------------------------*/
3065 int checkLabel(pCode *pc)
3069 if(pc && isPCI(pc)) {
3070 pbr = PCI(pc)->label;
3072 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3082 /*-----------------------------------------------------------------*/
3083 /* findLabelinpBlock - Search the pCode for a particular label */
3084 /*-----------------------------------------------------------------*/
3085 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3092 for(pc = pb->pcHead; pc; pc = pc->next)
3093 if(compareLabel(pc,pcop_label))
3099 /*-----------------------------------------------------------------*/
3100 /* findLabel - Search the pCode for a particular label */
3101 /*-----------------------------------------------------------------*/
3102 pCode * findLabel(pCodeOpLabel *pcop_label)
3110 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3111 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3115 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3119 /*-----------------------------------------------------------------*/
3120 /* findNextpCode - given a pCode, find the next of type 'pct' */
3121 /* in the linked list */
3122 /*-----------------------------------------------------------------*/
3123 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3136 /*-----------------------------------------------------------------*/
3137 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3138 /* in the linked list */
3139 /*-----------------------------------------------------------------*/
3140 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3152 /*-----------------------------------------------------------------*/
3153 /* findNextInstruction - given a pCode, find the next instruction */
3154 /* in the linked list */
3155 /*-----------------------------------------------------------------*/
3156 pCode * findNextInstruction(pCode *pci)
3161 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3165 fprintf(stderr,"findNextInstruction: ");
3166 printpCode(stderr, pc);
3171 //fprintf(stderr,"Couldn't find instruction\n");
3175 /*-----------------------------------------------------------------*/
3176 /* findNextInstruction - given a pCode, find the next instruction */
3177 /* in the linked list */
3178 /*-----------------------------------------------------------------*/
3179 pCode * findPrevInstruction(pCode *pci)
3181 return findPrevpCode(pci, PC_OPCODE);
3184 /*-----------------------------------------------------------------*/
3185 /* findFunctionEnd - given a pCode find the end of the function */
3186 /* that contains it */
3187 /*-----------------------------------------------------------------*/
3188 pCode * findFunctionEnd(pCode *pc)
3192 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3198 fprintf(stderr,"Couldn't find function end\n");
3203 /*-----------------------------------------------------------------*/
3204 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3205 /* instruction with which it is associated. */
3206 /*-----------------------------------------------------------------*/
3207 static void AnalyzeLabel(pCode *pc)
3216 static void AnalyzeGOTO(pCode *pc)
3219 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3223 static void AnalyzeSKIP(pCode *pc)
3226 pBranchLink(pc,findNextInstruction(pc->next));
3227 pBranchLink(pc,findNextInstruction(pc->next->next));
3231 static void AnalyzeRETURN(pCode *pc)
3234 // branch_link(pc,findFunctionEnd(pc->next));
3240 /*-----------------------------------------------------------------*/
3241 /*-----------------------------------------------------------------*/
3242 regs * getRegFromInstruction(pCode *pc)
3248 PCI(pc)->num_ops == 0 )
3251 switch(PCI(pc)->pcop->type) {
3254 return PCOR(PCI(pc)->pcop)->r;
3256 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3260 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3261 return PCOR(PCI(pc)->pcop)->r;
3264 if(PCOI(PCI(pc)->pcop)->r)
3265 return (PCOI(PCI(pc)->pcop)->r);
3267 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3268 return dirregWithName(PCI(pc)->pcop->name);
3269 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3272 return PCOR(PCI(pc)->pcop)->r;
3275 //fprintf(stderr, "getRegFromInstruction - dir\n");
3276 return PCOR(PCI(pc)->pcop)->r;
3278 //fprintf(stderr, "getRegFromInstruction - literal\n");
3282 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3283 //genericPrint(stderr, pc);
3291 /*-----------------------------------------------------------------*/
3292 /*-----------------------------------------------------------------*/
3294 void AnalyzepBlock(pBlock *pb)
3301 /* Find all of the registers used in this pBlock
3302 * by looking at each instruction and examining it's
3305 for(pc = pb->pcHead; pc; pc = pc->next) {
3307 /* Is this an instruction with operands? */
3308 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3310 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3312 /* Loop through all of the registers declared so far in
3313 this block and see if we find this one there */
3315 regs *r = setFirstItem(pb->tregisters);
3318 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3319 PCOR(PCI(pc)->pcop)->r = r;
3322 r = setNextItem(pb->tregisters);
3326 /* register wasn't found */
3327 //r = Safe_calloc(1, sizeof(regs));
3328 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3329 //addSet(&pb->tregisters, r);
3330 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3331 //PCOR(PCI(pc)->pcop)->r = r;
3332 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3334 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3337 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3338 if(PCOR(PCI(pc)->pcop)->r) {
3339 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3340 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3342 if(PCI(pc)->pcop->name)
3343 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3345 fprintf(stderr,"ERROR: NULL register\n");
3354 /*-----------------------------------------------------------------*/
3356 /*-----------------------------------------------------------------*/
3357 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3359 void InsertpFlow(pCode *pc, pCode **pflow)
3362 PCFL(*pflow)->end = pc;
3364 if(!pc || !pc->next)
3367 *pflow = newpCodeFlow();
3368 pCodeInsertAfter(pc, *pflow);
3371 /*-----------------------------------------------------------------*/
3372 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3373 /* the flow blocks. */
3375 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3376 * point the instruction flow changes.
3378 /*-----------------------------------------------------------------*/
3379 void BuildFlow(pBlock *pb)
3382 pCode *last_pci=NULL;
3389 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3390 /* Insert a pCodeFlow object at the beginning of a pBlock */
3392 InsertpFlow(pb->pcHead, &pflow);
3394 //pflow = newpCodeFlow(); /* Create a new Flow object */
3395 //pflow->next = pb->pcHead; /* Make the current head the next object */
3396 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3397 //pb->pcHead = pflow; /* Make the Flow object the head */
3400 for( pc = findNextInstruction(pb->pcHead);
3402 pc=findNextInstruction(pc)) {
3405 PCI(pc)->pcflow = PCFL(pflow);
3407 //fprintf(stderr," build: ");
3408 //pflow->print(stderr,pflow);
3410 if( PCI(pc)->isSkip) {
3412 /* The two instructions immediately following this one
3413 * mark the beginning of a new flow segment */
3415 while(pc && PCI(pc)->isSkip) {
3417 PCI(pc)->pcflow = PCFL(pflow);
3421 InsertpFlow(pc, &pflow);
3422 pc=findNextInstruction(pc->next);
3430 PCI(pc)->pcflow = PCFL(pflow);
3432 InsertpFlow(pc, &pflow);
3434 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3436 InsertpFlow(pc, &pflow);
3439 } else if (checkLabel(pc)) {
3441 /* This instruction marks the beginning of a
3442 * new flow segment */
3447 /* If the previous pCode is not a flow object, then
3448 * insert a new flow object. (This check prevents
3449 * two consecutive flow objects from being insert in
3450 * the case where a skip instruction preceeds an
3451 * instruction containing a label.) */
3453 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3454 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3456 PCI(pc)->pcflow = PCFL(pflow);
3463 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3465 PCFL(pflow)->end = pb->pcTail;
3468 /*-------------------------------------------------------------------*/
3469 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3470 /* the flow blocks. */
3472 * unBuildFlow removes pCodeFlow objects from a pCode chain
3474 /*-----------------------------------------------------------------*/
3475 void unBuildFlow(pBlock *pb)
3490 if(PCI(pc)->pcflow) {
3491 //free(PCI(pc)->pcflow);
3492 PCI(pc)->pcflow = NULL;
3495 } else if(isPCFL(pc) )
3504 /*-----------------------------------------------------------------*/
3505 /*-----------------------------------------------------------------*/
3506 void dumpCond(int cond)
3509 static char *pcc_str[] = {
3523 int ncond = sizeof(pcc_str) / sizeof(char *);
3526 fprintf(stderr, "0x%04X\n",cond);
3528 for(i=0,j=1; i<ncond; i++, j<<=1)
3530 fprintf(stderr, " %s\n",pcc_str[i]);
3534 /*-----------------------------------------------------------------*/
3535 /*-----------------------------------------------------------------*/
3536 void FlowStats(pCodeFlow *pcflow)
3544 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3546 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3549 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3554 fprintf(stderr, " FlowStats inCond: ");
3555 dumpCond(pcflow->inCond);
3556 fprintf(stderr, " FlowStats outCond: ");
3557 dumpCond(pcflow->outCond);
3561 /*-----------------------------------------------------------------*
3562 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3563 * if it affects the banking bits.
3565 * return: -1 == Banking bits are unaffected by this pCode.
3567 * return: > 0 == Banking bits are affected.
3569 * If the banking bits are affected, then the returned value describes
3570 * which bits are affected and how they're affected. The lower half
3571 * of the integer maps to the bits that are affected, the upper half
3572 * to whether they're set or cleared.
3574 *-----------------------------------------------------------------*/
3575 #define SET_BANK_BIT (1 << 16)
3576 #define CLR_BANK_BIT 0
3578 int isBankInstruction(pCode *pc)
3586 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3588 /* Check to see if the register banks are changing */
3589 if(PCI(pc)->isModReg) {
3591 pCodeOp *pcop = PCI(pc)->pcop;
3592 switch(PCI(pc)->op) {
3595 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3596 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3597 return SET_BANK_BIT | PIC_RP0_BIT;
3600 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3601 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3602 return CLR_BANK_BIT | PIC_RP0_BIT;
3607 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3608 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3609 return CLR_BANK_BIT | PIC_RP1_BIT;
3611 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3612 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3613 return CLR_BANK_BIT | PIC_RP1_BIT;
3617 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3618 //genericPrint(stderr, pc);
3629 /*-----------------------------------------------------------------*/
3630 /*-----------------------------------------------------------------*/
3631 void FillFlow(pCodeFlow *pcflow)
3640 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3642 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3645 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3652 isBankInstruction(pc);
3654 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3658 fprintf(stderr, " FillFlow - Bad end of flow\n");
3660 fprintf(stderr, " FillFlow - Ending flow with\n ");
3661 pc->print(stderr,pc);
3664 fprintf(stderr, " FillFlow inCond: ");
3665 dumpCond(pcflow->inCond);
3666 fprintf(stderr, " FillFlow outCond: ");
3667 dumpCond(pcflow->outCond);
3671 /*-----------------------------------------------------------------*/
3672 /*-----------------------------------------------------------------*/
3673 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3675 pCodeFlowLink *fromLink, *toLink;
3677 if(!from || !to || !to->pcflow || !from->pcflow)
3680 fromLink = newpCodeFlowLink(from->pcflow);
3681 toLink = newpCodeFlowLink(to->pcflow);
3683 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3684 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3688 /*-----------------------------------------------------------------*
3689 * void LinkFlow(pBlock *pb)
3691 * In BuildFlow, the PIC code has been partitioned into contiguous
3692 * non-branching segments. In LinkFlow, we determine the execution
3693 * order of these segments. For example, if one of the segments ends
3694 * with a skip, then we know that there are two possible flow segments
3695 * to which control may be passed.
3696 *-----------------------------------------------------------------*/
3697 void LinkFlow(pBlock *pb)
3703 //fprintf(stderr,"linkflow \n");
3705 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3707 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3710 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3712 //fprintf(stderr," link: ");
3713 //pcflow->print(stderr,pcflow);
3715 //FillFlow(PCFL(pcflow));
3717 pc = PCFL(pcflow)->end;
3719 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3720 if(isPCI_SKIP(pc)) {
3721 //fprintf(stderr, "ends with skip\n");
3722 //pc->print(stderr,pc);
3723 pct=findNextInstruction(pc->next);
3724 LinkFlow_pCode(PCI(pc),PCI(pct));
3725 pct=findNextInstruction(pct->next);
3726 LinkFlow_pCode(PCI(pc),PCI(pct));
3730 if(isPCI_BRANCH(pc)) {
3731 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3733 //fprintf(stderr, "ends with branch\n ");
3734 //pc->print(stderr,pc);
3736 if(!(pcol && isPCOLAB(pcol))) {
3737 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3738 pc->print(stderr,pc);
3739 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3744 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3745 LinkFlow_pCode(PCI(pc),PCI(pct));
3747 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3748 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3749 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3755 //fprintf(stderr, "ends with non-branching instruction:\n");
3756 //pc->print(stderr,pc);
3758 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3764 //fprintf(stderr, "ends with unknown\n");
3765 //pc->print(stderr,pc);
3769 //fprintf(stderr, "ends with nothing: ERROR\n");
3773 /*-----------------------------------------------------------------*/
3774 /*-----------------------------------------------------------------*/
3776 /*-----------------------------------------------------------------*/
3777 /*-----------------------------------------------------------------*/
3778 int isPCinFlow(pCode *pc, pCode *pcflow)
3784 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3787 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3793 /*-----------------------------------------------------------------*/
3794 /*-----------------------------------------------------------------*/
3795 void BanksUsedFlow2(pCode *pcflow)
3804 if(!isPCFL(pcflow)) {
3805 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3809 pc = findNextInstruction(pcflow->next);
3811 PCFL(pcflow)->lastBank = -1;
3813 while(isPCinFlow(pc,pcflow)) {
3815 int bank_selected = isBankInstruction(pc);
3817 //if(PCI(pc)->pcflow)
3818 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3820 if(bank_selected > 0) {
3821 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3823 /* This instruction is modifying banking bits before accessing registers */
3825 PCFL(pcflow)->firstBank = -1;
3827 if(PCFL(pcflow)->lastBank == -1)
3828 PCFL(pcflow)->lastBank = 0;
3830 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3831 if(bank_selected & SET_BANK_BIT)
3832 PCFL(pcflow)->lastBank |= bank;
3836 reg = getRegFromInstruction(pc);
3838 if(reg && !isREGinBank(reg, bank)) {
3839 int allbanks = REGallBanks(reg);
3841 PCFL(pcflow)->firstBank = allbanks;
3843 PCFL(pcflow)->lastBank = allbanks;
3850 pc = findNextInstruction(pc->next);
3853 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3854 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3859 /*-----------------------------------------------------------------*/
3860 /*-----------------------------------------------------------------*/
3861 void BanksUsedFlow(pBlock *pb)
3866 //pb->pcHead->print(stderr, pb->pcHead);
3868 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3869 //pcflow->print(stderr,pcflow);
3871 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3873 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3875 BanksUsedFlow2(pcflow);
3881 /*-----------------------------------------------------------------*/
3882 /*-----------------------------------------------------------------*/
3883 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3891 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3893 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3894 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3897 /* insert the bank switch after this pc instruction */
3898 pCode *pcnext = findNextInstruction(pc);
3899 pCodeInsertAfter(pc, new_pc);
3904 pCodeInsertAfter(pc->prev, new_pc);
3906 /* Move the label, if there is one */
3908 if(PCI(pc)->label) {
3909 PCI(new_pc)->label = PCI(pc)->label;
3910 PCI(pc)->label = NULL;
3913 /* The new instruction has the same pcflow block */
3914 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3917 /*-----------------------------------------------------------------*/
3918 /*-----------------------------------------------------------------*/
3919 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3930 pc = findNextInstruction(pcfl->pc.next);
3932 while(isPCinFlow(pc,PCODE(pcfl))) {
3934 reg = getRegFromInstruction(pc);
3937 fprintf(stderr, " %s ",reg->name);
3938 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3943 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
3944 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
3947 /* Examine the instruction before this one to make sure it is
3948 * not a skip type instruction */
3949 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3951 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3955 reg_bank = (reg) ? REG_BANK(reg) : 0;
3957 b = cur_bank ^ reg_bank;
3959 //fprintf(stderr, "Cool! can switch banks\n");
3960 cur_bank = reg_bank;
3965 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3968 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3969 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3973 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3974 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3976 insertBankSwitch(0, pc, -1, -1);
3982 //fprintf(stderr, "Bummer can't switch banks\n");
3988 pc = findNextInstruction(pc->next);
3992 if(pcprev && cur_bank) {
3993 /* Brute force - make sure that we point to bank 0 at the
3994 * end of each flow block */
3995 new_pc = newpCode(POC_BCF,
3996 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3997 pCodeInsertAfter(pcprev, new_pc);
4003 /*-----------------------------------------------------------------*/
4004 /*int compareBankFlow - compare the banking requirements between */
4006 /*-----------------------------------------------------------------*/
4007 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4010 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4013 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4016 if(pcflow->firstBank == -1)
4020 if(pcflowLink->pcflow->firstBank == -1) {
4021 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4022 pcflowLink->pcflow->to :
4023 pcflowLink->pcflow->from);
4024 return compareBankFlow(pcflow, pctl, toORfrom);
4028 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4031 pcflowLink->bank_conflict++;
4032 pcflowLink->pcflow->FromConflicts++;
4033 pcflow->ToConflicts++;
4036 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4039 pcflowLink->bank_conflict++;
4040 pcflowLink->pcflow->ToConflicts++;
4041 pcflow->FromConflicts++;
4045 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4046 pcflowLink->pcflow->pc.seq,
4047 pcflowLink->pcflow->FromConflicts,
4048 pcflowLink->pcflow->ToConflicts);
4053 /*-----------------------------------------------------------------*/
4054 /*-----------------------------------------------------------------*/
4055 void FixBankFlow(pBlock *pb)
4059 pCodeFlowLink *pcfl;
4061 pCode *pcflow_max_To=NULL;
4062 pCode *pcflow_max_From=NULL;
4063 int max_ToConflicts=0;
4064 int max_FromConflicts=0;
4066 //fprintf(stderr,"Fix Bank flow \n");
4067 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4071 First loop through all of the flow objects in this pcode block
4072 and fix the ones that have banking conflicts between the
4076 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4078 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4080 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4082 if(!isPCFL(pcflow)) {
4083 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4087 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4088 PCFL(pcflow)->firstBank >= 0 &&
4089 PCFL(pcflow)->lastBank >= 0 ) {
4091 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4092 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4094 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4095 BanksUsedFlow2(pcflow);
4100 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4102 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4104 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4109 if(!isPCFL(pcflow)) {
4110 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4114 PCFL(pcflow)->FromConflicts = 0;
4115 PCFL(pcflow)->ToConflicts = 0;
4120 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4121 pcfl = setFirstItem(PCFL(pcflow)->from);
4124 pc = PCODE(pcfl->pcflow);
4127 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4128 pc->print(stderr,pc);
4131 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4134 pcfl=setNextItem(PCFL(pcflow)->from);
4137 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4138 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4140 FixRegisterBankingInFlow(PCFL(pcflow),0);
4141 BanksUsedFlow2(pcflow);
4143 continue; /* Don't need to check the flow from here - it's already been fixed */
4150 pcfl = setFirstItem(PCFL(pcflow)->to);
4153 pc = PCODE(pcfl->pcflow);
4155 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4156 pc->print(stderr,pc);
4159 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4162 pcfl=setNextItem(PCFL(pcflow)->to);
4165 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4166 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4168 FixRegisterBankingInFlow(PCFL(pcflow),0);
4169 BanksUsedFlow2(pcflow);
4174 Loop through the flow objects again and find the ones with the
4178 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4180 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4182 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4183 pcflow_max_To = pcflow;
4185 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4186 pcflow_max_From = pcflow;
4190 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4191 PCFL(pcflow_max_To)->pc.seq,
4192 PCFL(pcflow_max_To)->ToConflicts);
4195 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4196 PCFL(pcflow_max_From)->pc.seq,
4197 PCFL(pcflow_max_From)->FromConflicts);
4201 /*-----------------------------------------------------------------*/
4202 /*-----------------------------------------------------------------*/
4203 void DumpFlow(pBlock *pb)
4207 pCodeFlowLink *pcfl;
4210 fprintf(stderr,"Dump flow \n");
4211 pb->pcHead->print(stderr, pb->pcHead);
4213 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4214 pcflow->print(stderr,pcflow);
4216 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4218 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4220 if(!isPCFL(pcflow)) {
4221 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4224 fprintf(stderr,"dumping: ");
4225 pcflow->print(stderr,pcflow);
4226 FlowStats(PCFL(pcflow));
4228 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4230 pc = PCODE(pcfl->pcflow);
4232 fprintf(stderr, " from seq %d:\n",pc->seq);
4234 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4235 pc->print(stderr,pc);
4240 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4242 pc = PCODE(pcfl->pcflow);
4244 fprintf(stderr, " to seq %d:\n",pc->seq);
4246 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4247 pc->print(stderr,pc);
4256 /*-----------------------------------------------------------------*/
4257 /*-----------------------------------------------------------------*/
4258 int OptimizepBlock(pBlock *pb)
4263 if(!pb || !peepOptimizing)
4266 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4268 for(pc = pb->pcHead; pc; pc = pc->next)
4269 matches += pCodePeepMatchRule(pc);
4272 pc = findNextInstruction(pb->pcHead);
4280 if(pCodePeepMatchRule(pc)) {
4285 pc = findNextInstruction(pcprev->next);
4287 pc = findNextInstruction(pb->pcHead);
4289 pc = findNextInstruction(pc->next);
4293 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4298 /*-----------------------------------------------------------------*/
4299 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4300 /*-----------------------------------------------------------------*/
4301 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4305 for(pc = pcs; pc; pc = pc->next) {
4307 if((pc->type == PC_OPCODE) &&
4309 (PCI(pc)->pcop->type == PO_LABEL) &&
4310 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4318 /*-----------------------------------------------------------------*/
4319 /*-----------------------------------------------------------------*/
4320 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4327 (PCI(pc)->pcop->type == PO_LABEL)) {
4329 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4331 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4333 free(pcol->pcop.name);
4335 /* If the key is negative, then we (probably) have a label to
4336 * a function and the name is already defined */
4339 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4343 //sprintf(buffer,"_%05d_DS_",pcl->key);
4345 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4347 pcol->pcop.name = Safe_strdup(s);
4348 pcol->key = pcl->key;
4349 //pc->print(stderr,pc);
4356 /*-----------------------------------------------------------------*/
4357 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4358 /* pCode chain if they're not used. */
4359 /*-----------------------------------------------------------------*/
4360 void pBlockRemoveUnusedLabels(pBlock *pb)
4362 pCode *pc; pCodeLabel *pcl;
4367 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4369 pBranch *pbr = PCI(pc)->label;
4370 if(pbr && pbr->next) {
4371 pCode *pcd = pb->pcHead;
4373 //fprintf(stderr, "multiple labels\n");
4374 //pc->print(stderr,pc);
4379 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4380 //fprintf(stderr,"Used by:\n");
4381 //pcd->print(stderr,pcd);
4383 exchangeLabels(PCL(pbr->pc),pcd);
4392 for(pc = pb->pcHead; pc; pc = pc->next) {
4394 if(isPCL(pc)) // pc->type == PC_LABEL)
4396 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4397 pcl = PCL(PCI(pc)->label->pc);
4400 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4402 /* This pCode is a label, so search the pBlock to see if anyone
4405 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4406 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4407 /* Couldn't find an instruction that refers to this label
4408 * So, unlink the pCode label from it's pCode chain
4409 * and destroy the label */
4410 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4412 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4413 if(pc->type == PC_LABEL) {
4415 pCodeLabelDestruct(pc);
4417 unlinkpCodeFromBranch(pc, PCODE(pcl));
4418 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4429 /*-----------------------------------------------------------------*/
4430 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4431 /* chain and put them into pBranches that are */
4432 /* associated with the appropriate pCode */
4434 /*-----------------------------------------------------------------*/
4435 void pBlockMergeLabels(pBlock *pb)
4438 pCode *pc, *pcnext=NULL;
4443 /* First, Try to remove any unused labels */
4444 //pBlockRemoveUnusedLabels(pb);
4446 /* Now loop through the pBlock and merge the labels with the opcodes */
4449 // for(pc = pb->pcHead; pc; pc = pc->next) {
4452 pCode *pcn = pc->next;
4454 if(pc->type == PC_LABEL) {
4456 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4457 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4458 if((pcnext = findNextInstruction(pc) )) {
4460 // Unlink the pCode label from it's pCode chain
4463 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4464 // And link it into the instruction's pBranch labels. (Note, since
4465 // it's possible to have multiple labels associated with one instruction
4466 // we must provide a means to accomodate the additional labels. Thus
4467 // the labels are placed into the singly-linked list "label" as
4468 // opposed to being a single member of the pCodeInstruction.)
4470 //_ALLOC(pbr,sizeof(pBranch));
4471 pbr = Safe_calloc(1,sizeof(pBranch));
4475 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4478 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4480 } else if(pc->type == PC_CSOURCE) {
4482 /* merge the source line symbolic info into the next instruction */
4483 if((pcnext = findNextInstruction(pc) )) {
4485 // Unlink the pCode label from it's pCode chain
4487 PCI(pcnext)->cline = PCCS(pc);
4488 //fprintf(stderr, "merging CSRC\n");
4489 //genericPrint(stderr,pcnext);
4495 pBlockRemoveUnusedLabels(pb);
4499 /*-----------------------------------------------------------------*/
4500 /*-----------------------------------------------------------------*/
4501 int OptimizepCode(char dbName)
4503 #define MAX_PASSES 4
4512 DFPRINTF((stderr," Optimizing pCode\n"));
4516 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4517 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4518 matches += OptimizepBlock(pb);
4521 while(matches && ++passes < MAX_PASSES);
4526 /*-----------------------------------------------------------------*/
4527 /* popCopyGPR2Bit - copy a pcode operator */
4528 /*-----------------------------------------------------------------*/
4530 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4534 pcop = newpCodeOpBit(pc->name, bitval, 0);
4536 if( !( (pcop->type == PO_LABEL) ||
4537 (pcop->type == PO_LITERAL) ||
4538 (pcop->type == PO_STR) ))
4539 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4547 /*-----------------------------------------------------------------*/
4548 /*-----------------------------------------------------------------*/
4549 int InstructionRegBank(pCode *pc)
4553 if( (reg = getRegFromInstruction(pc)) == NULL)
4556 return REG_BANK(reg);
4561 /*-----------------------------------------------------------------*/
4562 /*-----------------------------------------------------------------*/
4563 void FixRegisterBanking(pBlock *pb)
4574 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4575 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4578 /* loop through all of the flow blocks with in one pblock */
4580 //fprintf(stderr,"Register banking\n");
4583 /* at this point, pc should point to a PC_FLOW object */
4586 /* for each flow block, determine the register banking
4591 //genericPrint(stderr, pc);
4593 reg = getRegFromInstruction(pc);
4596 fprintf(stderr, " %s ",reg->name);
4597 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4598 reg->address,REG_BANK(reg),reg->isBitField);
4603 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4604 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4608 /* Examine the instruction before this one to make sure it is
4609 * not a skip type instruction */
4610 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4612 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4616 reg_bank = (reg) ? REG_BANK(reg) : 0;
4618 b = cur_bank ^ reg_bank;
4620 cur_bank = reg_bank;
4625 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4628 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4629 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4633 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4634 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4636 insertBankSwitch(0, pc, -1, -1);
4642 //fprintf(stderr, "Bummer can't switch banks\n");
4652 // } while(pc && !(isPCFL(pc)));
4657 if(pcprev && cur_bank) {
4659 int pos = 1; /* Assume that the bank swithc instruction(s)
4660 * are inserted after this instruction */
4662 if((PCI(pcprev)->op == POC_RETLW) ||
4663 (PCI(pcprev)->op == POC_RETURN) ||
4664 (PCI(pcprev)->op == POC_RETFIE)) {
4666 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4672 /* Brute force - make sure that we point to bank 0 at the
4673 * end of each flow block */
4675 switch(cur_bank & 3) {
4679 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4682 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4683 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4686 insertBankSwitch(pos, pcprev, -1, -1);
4691 new_pc = newpCode(POC_BCF,
4692 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4693 pCodeInsertAfter(pcprev, new_pc);
4696 //fprintf(stderr, "Brute force switch\n");
4705 if(reg && REG_BANK(reg)!=cur_bank) {
4706 //fprintf(stderr,"need to switch banks\n");
4707 /* Examine the instruction before this one to make sure it is
4708 * not a skip type instruction */
4709 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4710 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4711 int b = cur_bank ^ REG_BANK(reg);
4713 cur_bank = REG_BANK(reg);
4719 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4722 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4723 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4727 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4728 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4730 insertBankSwitch(0, pc, -1, -1);
4739 void pBlockDestruct(pBlock *pb)
4750 /*-----------------------------------------------------------------*/
4751 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4752 /* name dbName and combine them */
4753 /* into one block */
4754 /*-----------------------------------------------------------------*/
4755 void mergepBlocks(char dbName)
4758 pBlock *pb, *pbmerged = NULL,*pbn;
4760 pb = the_pFile->pbHead;
4762 //fprintf(stderr," merging blocks named %c\n",dbName);
4766 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4767 if( getpBlock_dbName(pb) == dbName) {
4769 //fprintf(stderr," merged block %c\n",dbName);
4774 addpCode2pBlock(pbmerged, pb->pcHead);
4775 /* addpCode2pBlock doesn't handle the tail: */
4776 pbmerged->pcTail = pb->pcTail;
4778 pb->prev->next = pbn;
4780 pbn->prev = pb->prev;
4785 //printpBlock(stderr, pbmerged);
4792 /*-----------------------------------------------------------------*/
4793 /* AnalyzeFlow - Examine the flow of the code and optimize */
4795 /* level 0 == minimal optimization */
4796 /* optimize registers that are used only by two instructions */
4797 /* level 1 == maximal optimization */
4798 /* optimize by looking at pairs of instructions that use the */
4800 /*-----------------------------------------------------------------*/
4802 void AnalyzeFlow(int level)
4804 static int times_called=0;
4812 /* if this is not the first time this function has been called,
4813 then clean up old flow information */
4814 if(times_called++) {
4815 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4818 RegsUnMapLiveRanges();
4824 /* Phase 2 - Flow Analysis - Register Banking
4826 * In this phase, the individual flow blocks are examined
4827 * and register banking is fixed.
4830 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4831 //FixRegisterBanking(pb);
4833 /* Phase 2 - Flow Analysis
4835 * In this phase, the pCode is partition into pCodeFlow
4836 * blocks. The flow blocks mark the points where a continuous
4837 * stream of instructions changes flow (e.g. because of
4838 * a call or goto or whatever).
4841 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4845 /* Phase 2 - Flow Analysis - linking flow blocks
4847 * In this phase, the individual flow blocks are examined
4848 * to determine their order of excution.
4851 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4854 /* Phase 3 - Flow Analysis - Flow Tree
4856 * In this phase, the individual flow blocks are examined
4857 * to determine their order of excution.
4860 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4864 /* Phase x - Flow Analysis - Used Banks
4866 * In this phase, the individual flow blocks are examined
4867 * to determine the Register Banks they use
4870 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4874 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4875 pCodeRegMapLiveRanges(pb);
4877 RemoveUnusedRegisters();
4879 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4880 pCodeRegOptimizeRegUsage(level);
4886 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4890 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4892 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4893 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4894 pcflow = pcflow->next) {
4896 FillFlow(PCFL(pcflow));
4901 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4903 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4904 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4905 pcflow = pcflow->next) {
4907 FlowStats(PCFL(pcflow));
4913 /*-----------------------------------------------------------------*/
4914 /* AnalyzeBanking - Called after the memory addresses have been */
4915 /* assigned to the registers. */
4917 /*-----------------------------------------------------------------*/
4919 void AnalyzeBanking(void)
4923 if(!picIsInitialized()) {
4924 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4925 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4926 fprintf(stderr,"support/scripts/inc2h.pl\n");
4927 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4932 /* Phase x - Flow Analysis - Used Banks
4934 * In this phase, the individual flow blocks are examined
4935 * to determine the Register Banks they use
4941 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4943 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4944 FixRegisterBanking(pb);
4948 /*-----------------------------------------------------------------*/
4949 /* buildCallTree - look at the flow and extract all of the calls */
4951 /*-----------------------------------------------------------------*/
4952 set *register_usage(pBlock *pb);
4954 void buildCallTree(void )
4965 /* Now build the call tree.
4966 First we examine all of the pCodes for functions.
4967 Keep in mind that the function boundaries coincide
4968 with pBlock boundaries.
4970 The algorithm goes something like this:
4971 We have two nested loops. The outer loop iterates
4972 through all of the pBlocks/functions. The inner
4973 loop iterates through all of the pCodes for
4974 a given pBlock. When we begin iterating through
4975 a pBlock, the variable pc_fstart, pCode of the start
4976 of a function, is cleared. We then search for pCodes
4977 of type PC_FUNCTION. When one is encountered, we
4978 initialize pc_fstart to this and at the same time
4979 associate a new pBranch object that signifies a
4980 branch entry. If a return is found, then this signifies
4981 a function exit point. We'll link the pCodes of these
4982 returns to the matching pc_fstart.
4984 When we're done, a doubly linked list of pBranches
4985 will exist. The head of this list is stored in
4986 `the_pFile', which is the meta structure for all
4987 of the pCode. Look at the printCallTree function
4988 on how the pBranches are linked together.
4991 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4992 pCode *pc_fstart=NULL;
4993 for(pc = pb->pcHead; pc; pc = pc->next) {
4995 if (PCF(pc)->fname) {
4997 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4998 //fprintf(stderr," found main \n");
4999 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5003 pbr = Safe_calloc(1,sizeof(pBranch));
5004 pbr->pc = pc_fstart = pc;
5007 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5009 // Here's a better way of doing the same:
5010 addSet(&pb->function_entries, pc);
5013 // Found an exit point in a function, e.g. return
5014 // (Note, there may be more than one return per function)
5016 pBranchLink(PCF(pc_fstart), PCF(pc));
5018 addSet(&pb->function_exits, pc);
5020 } else if(isCALL(pc)) {
5021 addSet(&pb->function_calls,pc);
5026 /* Re-allocate the registers so that there are no collisions
5027 * between local variables when one function call another */
5030 // pic14_deallocateAllRegs();
5032 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5039 /*-----------------------------------------------------------------*/
5040 /* AnalyzepCode - parse the pCode that has been generated and form */
5041 /* all of the logical connections. */
5043 /* Essentially what's done here is that the pCode flow is */
5045 /*-----------------------------------------------------------------*/
5047 void AnalyzepCode(char dbName)
5058 /* Phase 1 - Register allocation and peep hole optimization
5060 * The first part of the analysis is to determine the registers
5061 * that are used in the pCode. Once that is done, the peep rules
5062 * are applied to the code. We continue to loop until no more
5063 * peep rule optimizations are found (or until we exceed the
5064 * MAX_PASSES threshold).
5066 * When done, the required registers will be determined.
5072 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5073 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5075 /* First, merge the labels with the instructions */
5076 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5077 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5079 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5080 //fprintf(stderr," analyze and merging block %c\n",dbName);
5081 pBlockMergeLabels(pb);
5084 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5088 changes = OptimizepCode(dbName);
5090 } while(changes && (i++ < MAX_PASSES));
5095 /*-----------------------------------------------------------------*/
5096 /* ispCodeFunction - returns true if *pc is the pCode of a */
5098 /*-----------------------------------------------------------------*/
5099 bool ispCodeFunction(pCode *pc)
5102 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5108 /*-----------------------------------------------------------------*/
5109 /* findFunction - Search for a function by name (given the name) */
5110 /* in the set of all functions that are in a pBlock */
5111 /* (note - I expect this to change because I'm planning to limit */
5112 /* pBlock's to just one function declaration */
5113 /*-----------------------------------------------------------------*/
5114 pCode *findFunction(char *fname)
5121 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5123 pc = setFirstItem(pb->function_entries);
5126 if((pc->type == PC_FUNCTION) &&
5128 (strcmp(fname, PCF(pc)->fname)==0))
5131 pc = setNextItem(pb->function_entries);
5139 void MarkUsedRegisters(set *regset)
5144 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5145 r2 = pic14_regWithIdx(r1->rIdx);
5151 void pBlockStats(FILE *of, pBlock *pb)
5157 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5159 // for now just print the first element of each set
5160 pc = setFirstItem(pb->function_entries);
5162 fprintf(of,";entry: ");
5165 pc = setFirstItem(pb->function_exits);
5167 fprintf(of,";has an exit\n");
5171 pc = setFirstItem(pb->function_calls);
5173 fprintf(of,";functions called:\n");
5176 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5177 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5179 pc = setNextItem(pb->function_calls);
5183 r = setFirstItem(pb->tregisters);
5185 int n = elementsInSet(pb->tregisters);
5187 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5190 fprintf(of,"; %s\n",r->name);
5191 r = setNextItem(pb->tregisters);
5196 /*-----------------------------------------------------------------*/
5197 /*-----------------------------------------------------------------*/
5199 static void sequencepCode(void)
5205 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5207 pb->seq = GpCodeSequenceNumber+1;
5209 for( pc = pb->pcHead; pc; pc = pc->next)
5210 pc->seq = ++GpCodeSequenceNumber;
5216 /*-----------------------------------------------------------------*/
5217 /*-----------------------------------------------------------------*/
5218 set *register_usage(pBlock *pb)
5221 set *registers=NULL;
5222 set *registersInCallPath = NULL;
5224 /* check recursion */
5226 pc = setFirstItem(pb->function_entries);
5233 if(pc->type != PC_FUNCTION)
5234 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5236 pc = setFirstItem(pb->function_calls);
5237 for( ; pc; pc = setNextItem(pb->function_calls)) {
5239 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5240 char *dest = get_op_from_instruction(PCI(pc));
5242 pcn = findFunction(dest);
5244 registersInCallPath = register_usage(pcn->pb);
5246 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5251 pBlockStats(stderr,pb); // debug
5254 // Mark the registers in this block as used.
5256 MarkUsedRegisters(pb->tregisters);
5257 if(registersInCallPath) {
5258 /* registers were used in the functions this pBlock has called */
5259 /* so now, we need to see if these collide with the ones we are */
5262 regs *r1,*r2, *newreg;
5264 DFPRINTF((stderr,"comparing registers\n"));
5266 r1 = setFirstItem(registersInCallPath);
5269 r2 = setFirstItem(pb->tregisters);
5271 while(r2 && (r1->type != REG_STK)) {
5273 if(r2->rIdx == r1->rIdx) {
5274 newreg = pic14_findFreeReg(REG_GPR);
5278 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5282 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5283 r1->rIdx, newreg->rIdx));
5284 r2->rIdx = newreg->rIdx;
5285 //if(r2->name) free(r2->name);
5287 r2->name = Safe_strdup(newreg->name);
5291 newreg->wasUsed = 1;
5293 r2 = setNextItem(pb->tregisters);
5296 r1 = setNextItem(registersInCallPath);
5299 /* Collisions have been resolved. Now free the registers in the call path */
5300 r1 = setFirstItem(registersInCallPath);
5302 if(r1->type != REG_STK) {
5303 newreg = pic14_regWithIdx(r1->rIdx);
5306 r1 = setNextItem(registersInCallPath);
5310 // MarkUsedRegisters(pb->registers);
5312 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5315 DFPRINTF((stderr,"returning regs\n"));
5317 DFPRINTF((stderr,"not returning regs\n"));
5319 DFPRINTF((stderr,"pBlock after register optim.\n"));
5320 pBlockStats(stderr,pb); // debug
5326 /*-----------------------------------------------------------------*/
5327 /* printCallTree - writes the call tree to a file */
5329 /*-----------------------------------------------------------------*/
5330 void pct2(FILE *of,pBlock *pb,int indent)
5334 // set *registersInCallPath = NULL;
5340 return; //recursion ?
5342 pc = setFirstItem(pb->function_entries);
5349 for(i=0;i<indent;i++) // Indentation
5352 if(pc->type == PC_FUNCTION)
5353 fprintf(of,"%s\n",PCF(pc)->fname);
5358 pc = setFirstItem(pb->function_calls);
5359 for( ; pc; pc = setNextItem(pb->function_calls)) {
5361 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5362 char *dest = get_op_from_instruction(PCI(pc));
5364 pcn = findFunction(dest);
5366 pct2(of,pcn->pb,indent+1);
5368 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5376 /*-----------------------------------------------------------------*/
5377 /* printCallTree - writes the call tree to a file */
5379 /*-----------------------------------------------------------------*/
5381 void printCallTree(FILE *of)
5393 fprintf(of, "\npBlock statistics\n");
5394 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5399 fprintf(of,"Call Tree\n");
5400 pbr = the_pFile->functions;
5404 if(!ispCodeFunction(pc))
5405 fprintf(of,"bug in call tree");
5408 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5410 while(pc->next && !ispCodeFunction(pc->next)) {
5412 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5413 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5421 fprintf(of,"\n**************\n\na better call tree\n");
5422 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5427 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5428 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5434 /*-----------------------------------------------------------------*/
5436 /*-----------------------------------------------------------------*/
5438 void InlineFunction(pBlock *pb)
5446 pc = setFirstItem(pb->function_calls);
5448 for( ; pc; pc = setNextItem(pb->function_calls)) {
5451 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5457 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5459 //fprintf(stderr,"Cool can inline:\n");
5460 //pcn->print(stderr,pcn);
5462 //fprintf(stderr,"recursive call Inline\n");
5463 InlineFunction(pcn->pb);
5464 //fprintf(stderr,"return from recursive call Inline\n");
5467 At this point, *pc points to a CALL mnemonic, and
5468 *pcn points to the function that is being called.
5470 To in-line this call, we need to remove the CALL
5471 and RETURN(s), and link the function pCode in with
5477 /* Remove the CALL */
5481 /* remove callee pBlock from the pBlock linked list */
5482 removepBlock(pcn->pb);
5490 /* Remove the Function pCode */
5491 pct = findNextInstruction(pcn->next);
5493 /* Link the function with the callee */
5494 pc->next = pcn->next;
5495 pcn->next->prev = pc;
5497 /* Convert the function name into a label */
5499 pbr = Safe_calloc(1,sizeof(pBranch));
5500 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5502 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5503 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5505 /* turn all of the return's except the last into goto's */
5506 /* check case for 2 instruction pBlocks */
5507 pce = findNextInstruction(pcn->next);
5509 pCode *pce_next = findNextInstruction(pce->next);
5511 if(pce_next == NULL) {
5512 /* found the last return */
5513 pCode *pc_call_next = findNextInstruction(pc_call->next);
5515 //fprintf(stderr,"found last return\n");
5516 //pce->print(stderr,pce);
5517 pce->prev->next = pc_call->next;
5518 pc_call->next->prev = pce->prev;
5519 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5529 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5535 /*-----------------------------------------------------------------*/
5537 /*-----------------------------------------------------------------*/
5539 void InlinepCode(void)
5548 if(!functionInlining)
5551 /* Loop through all of the function definitions and count the
5552 * number of times each one is called */
5553 //fprintf(stderr,"inlining %d\n",__LINE__);
5555 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5557 pc = setFirstItem(pb->function_calls);
5559 for( ; pc; pc = setNextItem(pb->function_calls)) {
5562 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5563 if(pcn && isPCF(pcn)) {
5564 PCF(pcn)->ncalled++;
5567 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5572 //fprintf(stderr,"inlining %d\n",__LINE__);
5574 /* Now, Loop through the function definitions again, but this
5575 * time inline those functions that have only been called once. */
5577 InlineFunction(the_pFile->pbHead);
5578 //fprintf(stderr,"inlining %d\n",__LINE__);
5580 for(pb = the_pFile->pbHead; pb; pb = pb->next)