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_POINTER:
2231 case PO_GPR_REGISTER:
2233 pcop = newpCodeOpRegFromStr(name);
2235 pcop = newpCodeOpReg(-1);
2239 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2242 pcop->name = Safe_strdup(name);
2250 /*-----------------------------------------------------------------*/
2251 /*-----------------------------------------------------------------*/
2252 void pCodeConstString(char *name, char *value)
2256 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2261 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2265 sprintf(buffer,"; %s = %s",name,value);
2267 addpCode2pBlock(pb,newpCodeCharP(buffer));
2268 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2271 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2277 /*-----------------------------------------------------------------*/
2278 /*-----------------------------------------------------------------*/
2279 void pCodeReadCodeTable(void)
2283 fprintf(stderr, " %s\n",__FUNCTION__);
2285 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2289 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2290 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2291 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2292 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2294 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2295 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2296 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2297 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2302 /*-----------------------------------------------------------------*/
2303 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2304 /*-----------------------------------------------------------------*/
2305 void addpCode2pBlock(pBlock *pb, pCode *pc)
2312 /* If this is the first pcode to be added to a block that
2313 * was initialized with a NULL pcode, then go ahead and
2314 * make this pcode the head and tail */
2315 pb->pcHead = pb->pcTail = pc;
2318 pb->pcTail->next = pc;
2320 pc->prev = pb->pcTail;
2327 /*-----------------------------------------------------------------*/
2328 /* addpBlock - place a pBlock into the pFile */
2329 /*-----------------------------------------------------------------*/
2330 void addpBlock(pBlock *pb)
2332 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2335 /* First time called, we'll pass through here. */
2336 //_ALLOC(the_pFile,sizeof(pFile));
2337 the_pFile = Safe_calloc(1,sizeof(pFile));
2338 the_pFile->pbHead = the_pFile->pbTail = pb;
2339 the_pFile->functions = NULL;
2343 the_pFile->pbTail->next = pb;
2344 pb->prev = the_pFile->pbTail;
2346 the_pFile->pbTail = pb;
2349 /*-----------------------------------------------------------------*/
2350 /* removepBlock - remove a pBlock from the pFile */
2351 /*-----------------------------------------------------------------*/
2352 void removepBlock(pBlock *pb)
2360 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2362 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2365 if(pbs == the_pFile->pbHead)
2366 the_pFile->pbHead = pbs->next;
2368 if (pbs == the_pFile->pbTail)
2369 the_pFile->pbTail = pbs->prev;
2372 pbs->next->prev = pbs->prev;
2375 pbs->prev->next = pbs->next;
2382 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2386 /*-----------------------------------------------------------------*/
2387 /* printpCode - write the contents of a pCode to a file */
2388 /*-----------------------------------------------------------------*/
2389 void printpCode(FILE *of, pCode *pc)
2400 fprintf(of,"warning - unable to print pCode\n");
2403 /*-----------------------------------------------------------------*/
2404 /* printpBlock - write the contents of a pBlock to a file */
2405 /*-----------------------------------------------------------------*/
2406 void printpBlock(FILE *of, pBlock *pb)
2416 for(pc = pb->pcHead; pc; pc = pc->next)
2421 /*-----------------------------------------------------------------*/
2423 /* pCode processing */
2427 /*-----------------------------------------------------------------*/
2429 void unlinkpCode(pCode *pc)
2435 fprintf(stderr,"Unlinking: ");
2436 printpCode(stderr, pc);
2439 pc->prev->next = pc->next;
2441 pc->next->prev = pc->prev;
2443 pc->prev = pc->next = NULL;
2447 /*-----------------------------------------------------------------*/
2448 /*-----------------------------------------------------------------*/
2450 static void genericDestruct(pCode *pc)
2456 /* For instructions, tell the register (if there's one used)
2457 * that it's no longer needed */
2458 regs *reg = getRegFromInstruction(pc);
2460 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2463 /* Instead of deleting the memory used by this pCode, mark
2464 * the object as bad so that if there's a pointer to this pCode
2465 * dangling around somewhere then (hopefully) when the type is
2466 * checked we'll catch it.
2471 addpCode2pBlock(pb_dead_pcodes, pc);
2478 /*-----------------------------------------------------------------*/
2479 /*-----------------------------------------------------------------*/
2480 void pBlockRegs(FILE *of, pBlock *pb)
2485 r = setFirstItem(pb->tregisters);
2487 r = setNextItem(pb->tregisters);
2492 /*-----------------------------------------------------------------*/
2493 /*-----------------------------------------------------------------*/
2494 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2499 int use_buffer = 1; // copy the string to the passed buffer pointer
2504 use_buffer = 0; // Don't bother copying the string to the buffer.
2508 switch(pcop->type) {
2512 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2515 //return PCOR(pcop)->r->name;
2519 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2522 SAFE_snprintf(&buffer,&size,"%s",r->name);
2532 if(PCOI(pcop)->_const) {
2534 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2535 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2538 8 * PCOI(pcop)->offset );
2540 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2543 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2544 SAFE_snprintf(&s,&size,"(%s + %d)",
2546 PCOI(pcop)->index );
2548 if(PCOI(pcop)->offset)
2549 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2551 SAFE_snprintf(&s,&size,"%s",pcop->name);
2559 //size = sizeof(buffer);
2560 if( PCOR(pcop)->instance) {
2561 SAFE_snprintf(&s,&size,"(%s + %d)",
2563 PCOR(pcop)->instance );
2564 //fprintf(stderr,"PO_DIR %s\n",buffer);
2566 SAFE_snprintf(&s,&size,"%s",pcop->name);
2572 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2581 return "NO operand";
2585 /*-----------------------------------------------------------------*/
2586 /*-----------------------------------------------------------------*/
2587 static char *get_op_from_instruction( pCodeInstruction *pcc)
2591 return get_op(pcc->pcop,NULL,0);
2593 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2594 return ("ERROR Null: "__FUNCTION__);
2596 return ("ERROR Null: get_op_from_instruction");
2600 /*-----------------------------------------------------------------*/
2601 /*-----------------------------------------------------------------*/
2602 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2605 fprintf(of,"pcodeopprint- not implemented\n");
2608 /*-----------------------------------------------------------------*/
2609 /*-----------------------------------------------------------------*/
2610 char *pCode2str(char *str, size_t size, pCode *pc)
2618 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2620 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2622 if(PCI(pc)->isBitInst) {
2623 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2624 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2625 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2626 PCI(pc)->pcop->name ,
2627 PCI(pc)->pcop->name );
2629 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2630 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2631 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2632 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2634 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2635 //PCI(pc)->pcop->t.bit );
2638 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2639 if( PCI(pc)->num_ops == 2)
2640 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2642 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2645 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2647 if( PCI(pc)->num_ops == 2)
2648 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2656 /* assuming that comment ends with a \n */
2657 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2661 /* assuming that inline code ends with a \n */
2662 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2666 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2669 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2672 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2675 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2678 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2682 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2689 /*-----------------------------------------------------------------*/
2690 /* genericPrint - the contents of a pCode to a file */
2691 /*-----------------------------------------------------------------*/
2692 static void genericPrint(FILE *of, pCode *pc)
2700 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2704 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2708 // If the opcode has a label, print that first
2710 pBranch *pbl = PCI(pc)->label;
2711 while(pbl && pbl->pc) {
2712 if(pbl->pc->type == PC_LABEL)
2713 pCodePrintLabel(of, pbl->pc);
2719 genericPrint(of,PCODE(PCI(pc)->cline));
2724 pCode2str(str, 256, pc);
2726 fprintf(of,"%s",str);
2730 fprintf(of, "\t;key=%03x",pc->seq);
2732 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2737 pBranch *dpb = pc->to; // debug
2739 switch ( dpb->pc->type) {
2741 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2744 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2747 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2750 fprintf(of, "\t;flow");
2764 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2765 if(PCW(pc)->pci.label)
2766 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2768 if(PCW(pc)->operand) {
2769 fprintf(of,";\toperand ");
2770 pCodeOpPrint(of,PCW(pc)->operand );
2776 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2777 if(PCFL(pc)->ancestor)
2778 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2785 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2789 fprintf(of,"unknown pCode type %d\n",pc->type);
2794 /*-----------------------------------------------------------------*/
2795 /* pCodePrintFunction - prints function begin/end */
2796 /*-----------------------------------------------------------------*/
2798 static void pCodePrintFunction(FILE *of, pCode *pc)
2804 if( ((pCodeFunction *)pc)->modname)
2805 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2807 if(PCF(pc)->fname) {
2808 pBranch *exits = PCF(pc)->to;
2810 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2813 exits = exits->next;
2816 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2819 if((PCF(pc)->from &&
2820 PCF(pc)->from->pc->type == PC_FUNCTION &&
2821 PCF(PCF(pc)->from->pc)->fname) )
2822 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2824 fprintf(of,"; exit point [can't find entry point]\n");
2827 /*-----------------------------------------------------------------*/
2828 /* pCodePrintLabel - prints label */
2829 /*-----------------------------------------------------------------*/
2831 static void pCodePrintLabel(FILE *of, pCode *pc)
2838 fprintf(of,"%s\n",PCL(pc)->label);
2839 else if (PCL(pc)->key >=0)
2840 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2842 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2845 /*-----------------------------------------------------------------*/
2846 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2847 /* remove it if it is found. */
2848 /*-----------------------------------------------------------------*/
2849 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2856 if(pcl->type == PC_OPCODE)
2857 b = PCI(pcl)->label;
2859 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2864 //fprintf (stderr, "%s \n",__FUNCTION__);
2865 //pcl->print(stderr,pcl);
2866 //pc->print(stderr,pc);
2869 //fprintf (stderr, "found label\n");
2873 bprev->next = b->next; /* Not first pCode in chain */
2877 PCI(pcl)->label = b->next; /* First pCode in chain */
2880 return; /* A label can't occur more than once */
2888 /*-----------------------------------------------------------------*/
2889 /*-----------------------------------------------------------------*/
2890 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2909 /*-----------------------------------------------------------------*/
2910 /* pBranchLink - given two pcodes, this function will link them */
2911 /* together through their pBranches */
2912 /*-----------------------------------------------------------------*/
2913 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2917 // Declare a new branch object for the 'from' pCode.
2919 //_ALLOC(b,sizeof(pBranch));
2920 b = Safe_calloc(1,sizeof(pBranch));
2921 b->pc = PCODE(t); // The link to the 'to' pCode.
2924 f->to = pBranchAppend(f->to,b);
2926 // Now do the same for the 'to' pCode.
2928 //_ALLOC(b,sizeof(pBranch));
2929 b = Safe_calloc(1,sizeof(pBranch));
2933 t->from = pBranchAppend(t->from,b);
2938 /*-----------------------------------------------------------------*/
2939 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2941 /*-----------------------------------------------------------------*/
2942 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2955 /*-----------------------------------------------------------------*/
2956 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2957 /*-----------------------------------------------------------------*/
2958 static void pCodeUnlink(pCode *pc)
2963 if(!pc->prev || !pc->next) {
2964 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2968 /* first remove the pCode from the chain */
2969 pc->prev->next = pc->next;
2970 pc->next->prev = pc->prev;
2972 /* Now for the hard part... */
2974 /* Remove the branches */
2978 pc1 = pb1->pc; /* Get the pCode that branches to the
2979 * one we're unlinking */
2981 /* search for the link back to this pCode (the one we're
2983 if(pb2 = pBranchFind(pc1->to,pc)) {
2984 pb2->pc = pc->to->pc; // make the replacement
2986 /* if the pCode we're unlinking contains multiple 'to'
2987 * branches (e.g. this a skip instruction) then we need
2988 * to copy these extra branches to the chain. */
2990 pBranchAppend(pb2, pc->to->next);
2999 /*-----------------------------------------------------------------*/
3000 /*-----------------------------------------------------------------*/
3002 static void genericAnalyze(pCode *pc)
3012 // Go through the pCodes that are in pCode chain and link
3013 // them together through the pBranches. Note, the pCodes
3014 // are linked together as a contiguous stream like the
3015 // assembly source code lines. The linking here mimics this
3016 // except that comments are not linked in.
3018 pCode *npc = pc->next;
3020 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3021 pBranchLink(pc,npc);
3026 /* reached the end of the pcode chain without finding
3027 * an instruction we could link to. */
3031 fprintf(stderr,"analyze PC_FLOW\n");
3035 fprintf(stderr,,";A bad pCode is being used\n");
3041 /*-----------------------------------------------------------------*/
3042 /*-----------------------------------------------------------------*/
3043 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3047 if(pc->type == PC_LABEL) {
3048 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3051 if(pc->type == PC_OPCODE) {
3052 pbr = PCI(pc)->label;
3054 if(pbr->pc->type == PC_LABEL) {
3055 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3065 /*-----------------------------------------------------------------*/
3066 /*-----------------------------------------------------------------*/
3067 int checkLabel(pCode *pc)
3071 if(pc && isPCI(pc)) {
3072 pbr = PCI(pc)->label;
3074 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3084 /*-----------------------------------------------------------------*/
3085 /* findLabelinpBlock - Search the pCode for a particular label */
3086 /*-----------------------------------------------------------------*/
3087 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3094 for(pc = pb->pcHead; pc; pc = pc->next)
3095 if(compareLabel(pc,pcop_label))
3101 /*-----------------------------------------------------------------*/
3102 /* findLabel - Search the pCode for a particular label */
3103 /*-----------------------------------------------------------------*/
3104 pCode * findLabel(pCodeOpLabel *pcop_label)
3112 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3113 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3117 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3121 /*-----------------------------------------------------------------*/
3122 /* findNextpCode - given a pCode, find the next of type 'pct' */
3123 /* in the linked list */
3124 /*-----------------------------------------------------------------*/
3125 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3138 /*-----------------------------------------------------------------*/
3139 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3140 /* in the linked list */
3141 /*-----------------------------------------------------------------*/
3142 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3154 /*-----------------------------------------------------------------*/
3155 /* findNextInstruction - given a pCode, find the next instruction */
3156 /* in the linked list */
3157 /*-----------------------------------------------------------------*/
3158 pCode * findNextInstruction(pCode *pci)
3163 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3167 fprintf(stderr,"findNextInstruction: ");
3168 printpCode(stderr, pc);
3173 //fprintf(stderr,"Couldn't find instruction\n");
3177 /*-----------------------------------------------------------------*/
3178 /* findNextInstruction - given a pCode, find the next instruction */
3179 /* in the linked list */
3180 /*-----------------------------------------------------------------*/
3181 pCode * findPrevInstruction(pCode *pci)
3183 return findPrevpCode(pci, PC_OPCODE);
3186 /*-----------------------------------------------------------------*/
3187 /* findFunctionEnd - given a pCode find the end of the function */
3188 /* that contains it */
3189 /*-----------------------------------------------------------------*/
3190 pCode * findFunctionEnd(pCode *pc)
3194 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3200 fprintf(stderr,"Couldn't find function end\n");
3205 /*-----------------------------------------------------------------*/
3206 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3207 /* instruction with which it is associated. */
3208 /*-----------------------------------------------------------------*/
3209 static void AnalyzeLabel(pCode *pc)
3218 static void AnalyzeGOTO(pCode *pc)
3221 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3225 static void AnalyzeSKIP(pCode *pc)
3228 pBranchLink(pc,findNextInstruction(pc->next));
3229 pBranchLink(pc,findNextInstruction(pc->next->next));
3233 static void AnalyzeRETURN(pCode *pc)
3236 // branch_link(pc,findFunctionEnd(pc->next));
3242 /*-----------------------------------------------------------------*/
3243 /*-----------------------------------------------------------------*/
3244 regs * getRegFromInstruction(pCode *pc)
3250 PCI(pc)->num_ops == 0 )
3253 switch(PCI(pc)->pcop->type) {
3256 return PCOR(PCI(pc)->pcop)->r;
3258 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3262 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3263 return PCOR(PCI(pc)->pcop)->r;
3266 if(PCOI(PCI(pc)->pcop)->r)
3267 return (PCOI(PCI(pc)->pcop)->r);
3269 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3270 return dirregWithName(PCI(pc)->pcop->name);
3271 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3274 return PCOR(PCI(pc)->pcop)->r;
3277 //fprintf(stderr, "getRegFromInstruction - dir\n");
3278 return PCOR(PCI(pc)->pcop)->r;
3280 //fprintf(stderr, "getRegFromInstruction - literal\n");
3284 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3285 //genericPrint(stderr, pc);
3293 /*-----------------------------------------------------------------*/
3294 /*-----------------------------------------------------------------*/
3296 void AnalyzepBlock(pBlock *pb)
3303 /* Find all of the registers used in this pBlock
3304 * by looking at each instruction and examining it's
3307 for(pc = pb->pcHead; pc; pc = pc->next) {
3309 /* Is this an instruction with operands? */
3310 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3312 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3314 /* Loop through all of the registers declared so far in
3315 this block and see if we find this one there */
3317 regs *r = setFirstItem(pb->tregisters);
3320 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3321 PCOR(PCI(pc)->pcop)->r = r;
3324 r = setNextItem(pb->tregisters);
3328 /* register wasn't found */
3329 //r = Safe_calloc(1, sizeof(regs));
3330 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3331 //addSet(&pb->tregisters, r);
3332 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3333 //PCOR(PCI(pc)->pcop)->r = r;
3334 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3336 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3339 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3340 if(PCOR(PCI(pc)->pcop)->r) {
3341 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3342 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3344 if(PCI(pc)->pcop->name)
3345 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3347 fprintf(stderr,"ERROR: NULL register\n");
3356 /*-----------------------------------------------------------------*/
3358 /*-----------------------------------------------------------------*/
3359 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3361 void InsertpFlow(pCode *pc, pCode **pflow)
3364 PCFL(*pflow)->end = pc;
3366 if(!pc || !pc->next)
3369 *pflow = newpCodeFlow();
3370 pCodeInsertAfter(pc, *pflow);
3373 /*-----------------------------------------------------------------*/
3374 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3375 /* the flow blocks. */
3377 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3378 * point the instruction flow changes.
3380 /*-----------------------------------------------------------------*/
3381 void BuildFlow(pBlock *pb)
3384 pCode *last_pci=NULL;
3391 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3392 /* Insert a pCodeFlow object at the beginning of a pBlock */
3394 InsertpFlow(pb->pcHead, &pflow);
3396 //pflow = newpCodeFlow(); /* Create a new Flow object */
3397 //pflow->next = pb->pcHead; /* Make the current head the next object */
3398 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3399 //pb->pcHead = pflow; /* Make the Flow object the head */
3402 for( pc = findNextInstruction(pb->pcHead);
3404 pc=findNextInstruction(pc)) {
3407 PCI(pc)->pcflow = PCFL(pflow);
3409 //fprintf(stderr," build: ");
3410 //pflow->print(stderr,pflow);
3412 if( PCI(pc)->isSkip) {
3414 /* The two instructions immediately following this one
3415 * mark the beginning of a new flow segment */
3417 while(pc && PCI(pc)->isSkip) {
3419 PCI(pc)->pcflow = PCFL(pflow);
3423 InsertpFlow(pc, &pflow);
3424 pc=findNextInstruction(pc->next);
3432 PCI(pc)->pcflow = PCFL(pflow);
3434 InsertpFlow(pc, &pflow);
3436 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3438 InsertpFlow(pc, &pflow);
3441 } else if (checkLabel(pc)) {
3443 /* This instruction marks the beginning of a
3444 * new flow segment */
3449 /* If the previous pCode is not a flow object, then
3450 * insert a new flow object. (This check prevents
3451 * two consecutive flow objects from being insert in
3452 * the case where a skip instruction preceeds an
3453 * instruction containing a label.) */
3455 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3456 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3458 PCI(pc)->pcflow = PCFL(pflow);
3465 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3467 PCFL(pflow)->end = pb->pcTail;
3470 /*-------------------------------------------------------------------*/
3471 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3472 /* the flow blocks. */
3474 * unBuildFlow removes pCodeFlow objects from a pCode chain
3476 /*-----------------------------------------------------------------*/
3477 void unBuildFlow(pBlock *pb)
3492 if(PCI(pc)->pcflow) {
3493 //free(PCI(pc)->pcflow);
3494 PCI(pc)->pcflow = NULL;
3497 } else if(isPCFL(pc) )
3506 /*-----------------------------------------------------------------*/
3507 /*-----------------------------------------------------------------*/
3508 void dumpCond(int cond)
3511 static char *pcc_str[] = {
3525 int ncond = sizeof(pcc_str) / sizeof(char *);
3528 fprintf(stderr, "0x%04X\n",cond);
3530 for(i=0,j=1; i<ncond; i++, j<<=1)
3532 fprintf(stderr, " %s\n",pcc_str[i]);
3536 /*-----------------------------------------------------------------*/
3537 /*-----------------------------------------------------------------*/
3538 void FlowStats(pCodeFlow *pcflow)
3546 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3548 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3551 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3556 fprintf(stderr, " FlowStats inCond: ");
3557 dumpCond(pcflow->inCond);
3558 fprintf(stderr, " FlowStats outCond: ");
3559 dumpCond(pcflow->outCond);
3563 /*-----------------------------------------------------------------*
3564 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3565 * if it affects the banking bits.
3567 * return: -1 == Banking bits are unaffected by this pCode.
3569 * return: > 0 == Banking bits are affected.
3571 * If the banking bits are affected, then the returned value describes
3572 * which bits are affected and how they're affected. The lower half
3573 * of the integer maps to the bits that are affected, the upper half
3574 * to whether they're set or cleared.
3576 *-----------------------------------------------------------------*/
3577 #define SET_BANK_BIT (1 << 16)
3578 #define CLR_BANK_BIT 0
3580 int isBankInstruction(pCode *pc)
3588 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3590 /* Check to see if the register banks are changing */
3591 if(PCI(pc)->isModReg) {
3593 pCodeOp *pcop = PCI(pc)->pcop;
3594 switch(PCI(pc)->op) {
3597 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3598 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3599 return SET_BANK_BIT | PIC_RP0_BIT;
3602 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3603 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3604 return CLR_BANK_BIT | PIC_RP0_BIT;
3609 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3610 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3611 return CLR_BANK_BIT | PIC_RP1_BIT;
3613 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3614 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3615 return CLR_BANK_BIT | PIC_RP1_BIT;
3619 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3620 //genericPrint(stderr, pc);
3631 /*-----------------------------------------------------------------*/
3632 /*-----------------------------------------------------------------*/
3633 void FillFlow(pCodeFlow *pcflow)
3642 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3644 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3647 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3654 isBankInstruction(pc);
3656 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3660 fprintf(stderr, " FillFlow - Bad end of flow\n");
3662 fprintf(stderr, " FillFlow - Ending flow with\n ");
3663 pc->print(stderr,pc);
3666 fprintf(stderr, " FillFlow inCond: ");
3667 dumpCond(pcflow->inCond);
3668 fprintf(stderr, " FillFlow outCond: ");
3669 dumpCond(pcflow->outCond);
3673 /*-----------------------------------------------------------------*/
3674 /*-----------------------------------------------------------------*/
3675 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3677 pCodeFlowLink *fromLink, *toLink;
3679 if(!from || !to || !to->pcflow || !from->pcflow)
3682 fromLink = newpCodeFlowLink(from->pcflow);
3683 toLink = newpCodeFlowLink(to->pcflow);
3685 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3686 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3690 /*-----------------------------------------------------------------*
3691 * void LinkFlow(pBlock *pb)
3693 * In BuildFlow, the PIC code has been partitioned into contiguous
3694 * non-branching segments. In LinkFlow, we determine the execution
3695 * order of these segments. For example, if one of the segments ends
3696 * with a skip, then we know that there are two possible flow segments
3697 * to which control may be passed.
3698 *-----------------------------------------------------------------*/
3699 void LinkFlow(pBlock *pb)
3705 //fprintf(stderr,"linkflow \n");
3707 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3709 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3712 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3714 //fprintf(stderr," link: ");
3715 //pcflow->print(stderr,pcflow);
3717 //FillFlow(PCFL(pcflow));
3719 pc = PCFL(pcflow)->end;
3721 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3722 if(isPCI_SKIP(pc)) {
3723 //fprintf(stderr, "ends with skip\n");
3724 //pc->print(stderr,pc);
3725 pct=findNextInstruction(pc->next);
3726 LinkFlow_pCode(PCI(pc),PCI(pct));
3727 pct=findNextInstruction(pct->next);
3728 LinkFlow_pCode(PCI(pc),PCI(pct));
3732 if(isPCI_BRANCH(pc)) {
3733 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3735 //fprintf(stderr, "ends with branch\n ");
3736 //pc->print(stderr,pc);
3738 if(!(pcol && isPCOLAB(pcol))) {
3739 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3740 pc->print(stderr,pc);
3741 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3746 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3747 LinkFlow_pCode(PCI(pc),PCI(pct));
3749 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3750 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3751 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3757 //fprintf(stderr, "ends with non-branching instruction:\n");
3758 //pc->print(stderr,pc);
3760 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3766 //fprintf(stderr, "ends with unknown\n");
3767 //pc->print(stderr,pc);
3771 //fprintf(stderr, "ends with nothing: ERROR\n");
3775 /*-----------------------------------------------------------------*/
3776 /*-----------------------------------------------------------------*/
3778 /*-----------------------------------------------------------------*/
3779 /*-----------------------------------------------------------------*/
3780 int isPCinFlow(pCode *pc, pCode *pcflow)
3786 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3789 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3795 /*-----------------------------------------------------------------*/
3796 /*-----------------------------------------------------------------*/
3797 void BanksUsedFlow2(pCode *pcflow)
3806 if(!isPCFL(pcflow)) {
3807 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3811 pc = findNextInstruction(pcflow->next);
3813 PCFL(pcflow)->lastBank = -1;
3815 while(isPCinFlow(pc,pcflow)) {
3817 int bank_selected = isBankInstruction(pc);
3819 //if(PCI(pc)->pcflow)
3820 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3822 if(bank_selected > 0) {
3823 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3825 /* This instruction is modifying banking bits before accessing registers */
3827 PCFL(pcflow)->firstBank = -1;
3829 if(PCFL(pcflow)->lastBank == -1)
3830 PCFL(pcflow)->lastBank = 0;
3832 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3833 if(bank_selected & SET_BANK_BIT)
3834 PCFL(pcflow)->lastBank |= bank;
3838 reg = getRegFromInstruction(pc);
3840 if(reg && !isREGinBank(reg, bank)) {
3841 int allbanks = REGallBanks(reg);
3843 PCFL(pcflow)->firstBank = allbanks;
3845 PCFL(pcflow)->lastBank = allbanks;
3852 pc = findNextInstruction(pc->next);
3855 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3856 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3861 /*-----------------------------------------------------------------*/
3862 /*-----------------------------------------------------------------*/
3863 void BanksUsedFlow(pBlock *pb)
3868 //pb->pcHead->print(stderr, pb->pcHead);
3870 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3871 //pcflow->print(stderr,pcflow);
3873 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3875 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3877 BanksUsedFlow2(pcflow);
3883 /*-----------------------------------------------------------------*/
3884 /*-----------------------------------------------------------------*/
3885 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3893 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3895 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3896 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3899 /* insert the bank switch after this pc instruction */
3900 pCode *pcnext = findNextInstruction(pc);
3901 pCodeInsertAfter(pc, new_pc);
3906 pCodeInsertAfter(pc->prev, new_pc);
3908 /* Move the label, if there is one */
3910 if(PCI(pc)->label) {
3911 PCI(new_pc)->label = PCI(pc)->label;
3912 PCI(pc)->label = NULL;
3915 /* The new instruction has the same pcflow block */
3916 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3919 /*-----------------------------------------------------------------*/
3920 /*-----------------------------------------------------------------*/
3921 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3932 pc = findNextInstruction(pcfl->pc.next);
3934 while(isPCinFlow(pc,PCODE(pcfl))) {
3936 reg = getRegFromInstruction(pc);
3939 fprintf(stderr, " %s ",reg->name);
3940 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3945 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
3946 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
3949 /* Examine the instruction before this one to make sure it is
3950 * not a skip type instruction */
3951 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3953 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3957 reg_bank = (reg) ? REG_BANK(reg) : 0;
3959 b = cur_bank ^ reg_bank;
3961 //fprintf(stderr, "Cool! can switch banks\n");
3962 cur_bank = reg_bank;
3967 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3970 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3971 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3975 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3976 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3978 insertBankSwitch(0, pc, -1, -1);
3984 //fprintf(stderr, "Bummer can't switch banks\n");
3990 pc = findNextInstruction(pc->next);
3994 if(pcprev && cur_bank) {
3995 /* Brute force - make sure that we point to bank 0 at the
3996 * end of each flow block */
3997 new_pc = newpCode(POC_BCF,
3998 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3999 pCodeInsertAfter(pcprev, new_pc);
4005 /*-----------------------------------------------------------------*/
4006 /*int compareBankFlow - compare the banking requirements between */
4008 /*-----------------------------------------------------------------*/
4009 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4012 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4015 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4018 if(pcflow->firstBank == -1)
4022 if(pcflowLink->pcflow->firstBank == -1) {
4023 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4024 pcflowLink->pcflow->to :
4025 pcflowLink->pcflow->from);
4026 return compareBankFlow(pcflow, pctl, toORfrom);
4030 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4033 pcflowLink->bank_conflict++;
4034 pcflowLink->pcflow->FromConflicts++;
4035 pcflow->ToConflicts++;
4038 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4041 pcflowLink->bank_conflict++;
4042 pcflowLink->pcflow->ToConflicts++;
4043 pcflow->FromConflicts++;
4047 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4048 pcflowLink->pcflow->pc.seq,
4049 pcflowLink->pcflow->FromConflicts,
4050 pcflowLink->pcflow->ToConflicts);
4055 /*-----------------------------------------------------------------*/
4056 /*-----------------------------------------------------------------*/
4057 void FixBankFlow(pBlock *pb)
4061 pCodeFlowLink *pcfl;
4063 pCode *pcflow_max_To=NULL;
4064 pCode *pcflow_max_From=NULL;
4065 int max_ToConflicts=0;
4066 int max_FromConflicts=0;
4068 //fprintf(stderr,"Fix Bank flow \n");
4069 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4073 First loop through all of the flow objects in this pcode block
4074 and fix the ones that have banking conflicts between the
4078 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4080 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4082 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4084 if(!isPCFL(pcflow)) {
4085 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4089 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4090 PCFL(pcflow)->firstBank >= 0 &&
4091 PCFL(pcflow)->lastBank >= 0 ) {
4093 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4094 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4096 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4097 BanksUsedFlow2(pcflow);
4102 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4104 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4106 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4111 if(!isPCFL(pcflow)) {
4112 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4116 PCFL(pcflow)->FromConflicts = 0;
4117 PCFL(pcflow)->ToConflicts = 0;
4122 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4123 pcfl = setFirstItem(PCFL(pcflow)->from);
4126 pc = PCODE(pcfl->pcflow);
4129 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4130 pc->print(stderr,pc);
4133 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4136 pcfl=setNextItem(PCFL(pcflow)->from);
4139 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4140 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4142 FixRegisterBankingInFlow(PCFL(pcflow),0);
4143 BanksUsedFlow2(pcflow);
4145 continue; /* Don't need to check the flow from here - it's already been fixed */
4152 pcfl = setFirstItem(PCFL(pcflow)->to);
4155 pc = PCODE(pcfl->pcflow);
4157 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4158 pc->print(stderr,pc);
4161 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4164 pcfl=setNextItem(PCFL(pcflow)->to);
4167 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4168 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4170 FixRegisterBankingInFlow(PCFL(pcflow),0);
4171 BanksUsedFlow2(pcflow);
4176 Loop through the flow objects again and find the ones with the
4180 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4182 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4184 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4185 pcflow_max_To = pcflow;
4187 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4188 pcflow_max_From = pcflow;
4192 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4193 PCFL(pcflow_max_To)->pc.seq,
4194 PCFL(pcflow_max_To)->ToConflicts);
4197 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4198 PCFL(pcflow_max_From)->pc.seq,
4199 PCFL(pcflow_max_From)->FromConflicts);
4203 /*-----------------------------------------------------------------*/
4204 /*-----------------------------------------------------------------*/
4205 void DumpFlow(pBlock *pb)
4209 pCodeFlowLink *pcfl;
4212 fprintf(stderr,"Dump flow \n");
4213 pb->pcHead->print(stderr, pb->pcHead);
4215 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4216 pcflow->print(stderr,pcflow);
4218 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4220 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4222 if(!isPCFL(pcflow)) {
4223 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4226 fprintf(stderr,"dumping: ");
4227 pcflow->print(stderr,pcflow);
4228 FlowStats(PCFL(pcflow));
4230 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4232 pc = PCODE(pcfl->pcflow);
4234 fprintf(stderr, " from seq %d:\n",pc->seq);
4236 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4237 pc->print(stderr,pc);
4242 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4244 pc = PCODE(pcfl->pcflow);
4246 fprintf(stderr, " to seq %d:\n",pc->seq);
4248 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4249 pc->print(stderr,pc);
4258 /*-----------------------------------------------------------------*/
4259 /*-----------------------------------------------------------------*/
4260 int OptimizepBlock(pBlock *pb)
4265 if(!pb || !peepOptimizing)
4268 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4270 for(pc = pb->pcHead; pc; pc = pc->next)
4271 matches += pCodePeepMatchRule(pc);
4274 pc = findNextInstruction(pb->pcHead);
4282 if(pCodePeepMatchRule(pc)) {
4287 pc = findNextInstruction(pcprev->next);
4289 pc = findNextInstruction(pb->pcHead);
4291 pc = findNextInstruction(pc->next);
4295 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4300 /*-----------------------------------------------------------------*/
4301 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4302 /*-----------------------------------------------------------------*/
4303 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4307 for(pc = pcs; pc; pc = pc->next) {
4309 if((pc->type == PC_OPCODE) &&
4311 (PCI(pc)->pcop->type == PO_LABEL) &&
4312 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4320 /*-----------------------------------------------------------------*/
4321 /*-----------------------------------------------------------------*/
4322 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4329 (PCI(pc)->pcop->type == PO_LABEL)) {
4331 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4333 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4335 free(pcol->pcop.name);
4337 /* If the key is negative, then we (probably) have a label to
4338 * a function and the name is already defined */
4341 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4345 //sprintf(buffer,"_%05d_DS_",pcl->key);
4347 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4349 pcol->pcop.name = Safe_strdup(s);
4350 pcol->key = pcl->key;
4351 //pc->print(stderr,pc);
4358 /*-----------------------------------------------------------------*/
4359 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4360 /* pCode chain if they're not used. */
4361 /*-----------------------------------------------------------------*/
4362 void pBlockRemoveUnusedLabels(pBlock *pb)
4364 pCode *pc; pCodeLabel *pcl;
4369 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4371 pBranch *pbr = PCI(pc)->label;
4372 if(pbr && pbr->next) {
4373 pCode *pcd = pb->pcHead;
4375 //fprintf(stderr, "multiple labels\n");
4376 //pc->print(stderr,pc);
4381 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4382 //fprintf(stderr,"Used by:\n");
4383 //pcd->print(stderr,pcd);
4385 exchangeLabels(PCL(pbr->pc),pcd);
4394 for(pc = pb->pcHead; pc; pc = pc->next) {
4396 if(isPCL(pc)) // pc->type == PC_LABEL)
4398 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4399 pcl = PCL(PCI(pc)->label->pc);
4402 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4404 /* This pCode is a label, so search the pBlock to see if anyone
4407 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4408 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4409 /* Couldn't find an instruction that refers to this label
4410 * So, unlink the pCode label from it's pCode chain
4411 * and destroy the label */
4412 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4414 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4415 if(pc->type == PC_LABEL) {
4417 pCodeLabelDestruct(pc);
4419 unlinkpCodeFromBranch(pc, PCODE(pcl));
4420 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4431 /*-----------------------------------------------------------------*/
4432 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4433 /* chain and put them into pBranches that are */
4434 /* associated with the appropriate pCode */
4436 /*-----------------------------------------------------------------*/
4437 void pBlockMergeLabels(pBlock *pb)
4440 pCode *pc, *pcnext=NULL;
4445 /* First, Try to remove any unused labels */
4446 //pBlockRemoveUnusedLabels(pb);
4448 /* Now loop through the pBlock and merge the labels with the opcodes */
4451 // for(pc = pb->pcHead; pc; pc = pc->next) {
4454 pCode *pcn = pc->next;
4456 if(pc->type == PC_LABEL) {
4458 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4459 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4460 if((pcnext = findNextInstruction(pc) )) {
4462 // Unlink the pCode label from it's pCode chain
4465 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4466 // And link it into the instruction's pBranch labels. (Note, since
4467 // it's possible to have multiple labels associated with one instruction
4468 // we must provide a means to accomodate the additional labels. Thus
4469 // the labels are placed into the singly-linked list "label" as
4470 // opposed to being a single member of the pCodeInstruction.)
4472 //_ALLOC(pbr,sizeof(pBranch));
4473 pbr = Safe_calloc(1,sizeof(pBranch));
4477 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4480 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4482 } else if(pc->type == PC_CSOURCE) {
4484 /* merge the source line symbolic info into the next instruction */
4485 if((pcnext = findNextInstruction(pc) )) {
4487 // Unlink the pCode label from it's pCode chain
4489 PCI(pcnext)->cline = PCCS(pc);
4490 //fprintf(stderr, "merging CSRC\n");
4491 //genericPrint(stderr,pcnext);
4497 pBlockRemoveUnusedLabels(pb);
4501 /*-----------------------------------------------------------------*/
4502 /*-----------------------------------------------------------------*/
4503 int OptimizepCode(char dbName)
4505 #define MAX_PASSES 4
4514 DFPRINTF((stderr," Optimizing pCode\n"));
4518 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4519 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4520 matches += OptimizepBlock(pb);
4523 while(matches && ++passes < MAX_PASSES);
4528 /*-----------------------------------------------------------------*/
4529 /* popCopyGPR2Bit - copy a pcode operator */
4530 /*-----------------------------------------------------------------*/
4532 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4536 pcop = newpCodeOpBit(pc->name, bitval, 0);
4538 if( !( (pcop->type == PO_LABEL) ||
4539 (pcop->type == PO_LITERAL) ||
4540 (pcop->type == PO_STR) ))
4541 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4549 /*-----------------------------------------------------------------*/
4550 /*-----------------------------------------------------------------*/
4551 int InstructionRegBank(pCode *pc)
4555 if( (reg = getRegFromInstruction(pc)) == NULL)
4558 return REG_BANK(reg);
4563 /*-----------------------------------------------------------------*/
4564 /*-----------------------------------------------------------------*/
4565 void FixRegisterBanking(pBlock *pb)
4576 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4577 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4580 /* loop through all of the flow blocks with in one pblock */
4582 //fprintf(stderr,"Register banking\n");
4585 /* at this point, pc should point to a PC_FLOW object */
4588 /* for each flow block, determine the register banking
4593 //genericPrint(stderr, pc);
4595 reg = getRegFromInstruction(pc);
4598 fprintf(stderr, " %s ",reg->name);
4599 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4600 reg->address,REG_BANK(reg),reg->isBitField);
4605 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4606 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4610 /* Examine the instruction before this one to make sure it is
4611 * not a skip type instruction */
4612 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4614 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4618 reg_bank = (reg) ? REG_BANK(reg) : 0;
4620 b = cur_bank ^ reg_bank;
4622 cur_bank = reg_bank;
4627 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4630 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4631 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4635 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4636 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4638 insertBankSwitch(0, pc, -1, -1);
4644 //fprintf(stderr, "Bummer can't switch banks\n");
4654 // } while(pc && !(isPCFL(pc)));
4659 if(pcprev && cur_bank) {
4661 int pos = 1; /* Assume that the bank swithc instruction(s)
4662 * are inserted after this instruction */
4664 if((PCI(pcprev)->op == POC_RETLW) ||
4665 (PCI(pcprev)->op == POC_RETURN) ||
4666 (PCI(pcprev)->op == POC_RETFIE)) {
4668 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4674 /* Brute force - make sure that we point to bank 0 at the
4675 * end of each flow block */
4677 switch(cur_bank & 3) {
4681 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4684 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4685 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4688 insertBankSwitch(pos, pcprev, -1, -1);
4693 new_pc = newpCode(POC_BCF,
4694 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4695 pCodeInsertAfter(pcprev, new_pc);
4698 //fprintf(stderr, "Brute force switch\n");
4707 if(reg && REG_BANK(reg)!=cur_bank) {
4708 //fprintf(stderr,"need to switch banks\n");
4709 /* Examine the instruction before this one to make sure it is
4710 * not a skip type instruction */
4711 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4712 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4713 int b = cur_bank ^ REG_BANK(reg);
4715 cur_bank = REG_BANK(reg);
4721 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4724 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4725 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4729 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4730 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4732 insertBankSwitch(0, pc, -1, -1);
4741 void pBlockDestruct(pBlock *pb)
4752 /*-----------------------------------------------------------------*/
4753 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4754 /* name dbName and combine them */
4755 /* into one block */
4756 /*-----------------------------------------------------------------*/
4757 void mergepBlocks(char dbName)
4760 pBlock *pb, *pbmerged = NULL,*pbn;
4762 pb = the_pFile->pbHead;
4764 //fprintf(stderr," merging blocks named %c\n",dbName);
4768 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4769 if( getpBlock_dbName(pb) == dbName) {
4771 //fprintf(stderr," merged block %c\n",dbName);
4776 addpCode2pBlock(pbmerged, pb->pcHead);
4777 /* addpCode2pBlock doesn't handle the tail: */
4778 pbmerged->pcTail = pb->pcTail;
4780 pb->prev->next = pbn;
4782 pbn->prev = pb->prev;
4787 //printpBlock(stderr, pbmerged);
4794 /*-----------------------------------------------------------------*/
4795 /* AnalyzeFlow - Examine the flow of the code and optimize */
4797 /* level 0 == minimal optimization */
4798 /* optimize registers that are used only by two instructions */
4799 /* level 1 == maximal optimization */
4800 /* optimize by looking at pairs of instructions that use the */
4802 /*-----------------------------------------------------------------*/
4804 void AnalyzeFlow(int level)
4806 static int times_called=0;
4814 /* if this is not the first time this function has been called,
4815 then clean up old flow information */
4816 if(times_called++) {
4817 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4820 RegsUnMapLiveRanges();
4826 /* Phase 2 - Flow Analysis - Register Banking
4828 * In this phase, the individual flow blocks are examined
4829 * and register banking is fixed.
4832 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4833 //FixRegisterBanking(pb);
4835 /* Phase 2 - Flow Analysis
4837 * In this phase, the pCode is partition into pCodeFlow
4838 * blocks. The flow blocks mark the points where a continuous
4839 * stream of instructions changes flow (e.g. because of
4840 * a call or goto or whatever).
4843 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4847 /* Phase 2 - Flow Analysis - linking flow blocks
4849 * In this phase, the individual flow blocks are examined
4850 * to determine their order of excution.
4853 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4856 /* Phase 3 - Flow Analysis - Flow Tree
4858 * In this phase, the individual flow blocks are examined
4859 * to determine their order of excution.
4862 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4866 /* Phase x - Flow Analysis - Used Banks
4868 * In this phase, the individual flow blocks are examined
4869 * to determine the Register Banks they use
4872 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4876 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4877 pCodeRegMapLiveRanges(pb);
4879 RemoveUnusedRegisters();
4881 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4882 pCodeRegOptimizeRegUsage(level);
4888 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4892 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4894 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4895 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4896 pcflow = pcflow->next) {
4898 FillFlow(PCFL(pcflow));
4903 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4905 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4906 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4907 pcflow = pcflow->next) {
4909 FlowStats(PCFL(pcflow));
4915 /*-----------------------------------------------------------------*/
4916 /* AnalyzeBanking - Called after the memory addresses have been */
4917 /* assigned to the registers. */
4919 /*-----------------------------------------------------------------*/
4921 void AnalyzeBanking(void)
4925 if(!picIsInitialized()) {
4926 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4927 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4928 fprintf(stderr,"support/scripts/inc2h.pl\n");
4929 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4934 /* Phase x - Flow Analysis - Used Banks
4936 * In this phase, the individual flow blocks are examined
4937 * to determine the Register Banks they use
4943 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4945 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4946 FixRegisterBanking(pb);
4950 /*-----------------------------------------------------------------*/
4951 /* buildCallTree - look at the flow and extract all of the calls */
4953 /*-----------------------------------------------------------------*/
4954 set *register_usage(pBlock *pb);
4956 void buildCallTree(void )
4967 /* Now build the call tree.
4968 First we examine all of the pCodes for functions.
4969 Keep in mind that the function boundaries coincide
4970 with pBlock boundaries.
4972 The algorithm goes something like this:
4973 We have two nested loops. The outer loop iterates
4974 through all of the pBlocks/functions. The inner
4975 loop iterates through all of the pCodes for
4976 a given pBlock. When we begin iterating through
4977 a pBlock, the variable pc_fstart, pCode of the start
4978 of a function, is cleared. We then search for pCodes
4979 of type PC_FUNCTION. When one is encountered, we
4980 initialize pc_fstart to this and at the same time
4981 associate a new pBranch object that signifies a
4982 branch entry. If a return is found, then this signifies
4983 a function exit point. We'll link the pCodes of these
4984 returns to the matching pc_fstart.
4986 When we're done, a doubly linked list of pBranches
4987 will exist. The head of this list is stored in
4988 `the_pFile', which is the meta structure for all
4989 of the pCode. Look at the printCallTree function
4990 on how the pBranches are linked together.
4993 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4994 pCode *pc_fstart=NULL;
4995 for(pc = pb->pcHead; pc; pc = pc->next) {
4997 if (PCF(pc)->fname) {
4999 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5000 //fprintf(stderr," found main \n");
5001 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5005 pbr = Safe_calloc(1,sizeof(pBranch));
5006 pbr->pc = pc_fstart = pc;
5009 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5011 // Here's a better way of doing the same:
5012 addSet(&pb->function_entries, pc);
5015 // Found an exit point in a function, e.g. return
5016 // (Note, there may be more than one return per function)
5018 pBranchLink(PCF(pc_fstart), PCF(pc));
5020 addSet(&pb->function_exits, pc);
5022 } else if(isCALL(pc)) {
5023 addSet(&pb->function_calls,pc);
5028 /* Re-allocate the registers so that there are no collisions
5029 * between local variables when one function call another */
5032 // pic14_deallocateAllRegs();
5034 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5041 /*-----------------------------------------------------------------*/
5042 /* AnalyzepCode - parse the pCode that has been generated and form */
5043 /* all of the logical connections. */
5045 /* Essentially what's done here is that the pCode flow is */
5047 /*-----------------------------------------------------------------*/
5049 void AnalyzepCode(char dbName)
5060 /* Phase 1 - Register allocation and peep hole optimization
5062 * The first part of the analysis is to determine the registers
5063 * that are used in the pCode. Once that is done, the peep rules
5064 * are applied to the code. We continue to loop until no more
5065 * peep rule optimizations are found (or until we exceed the
5066 * MAX_PASSES threshold).
5068 * When done, the required registers will be determined.
5074 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5075 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5077 /* First, merge the labels with the instructions */
5078 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5079 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5081 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5082 //fprintf(stderr," analyze and merging block %c\n",dbName);
5083 pBlockMergeLabels(pb);
5086 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5090 changes = OptimizepCode(dbName);
5092 } while(changes && (i++ < MAX_PASSES));
5097 /*-----------------------------------------------------------------*/
5098 /* ispCodeFunction - returns true if *pc is the pCode of a */
5100 /*-----------------------------------------------------------------*/
5101 bool ispCodeFunction(pCode *pc)
5104 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5110 /*-----------------------------------------------------------------*/
5111 /* findFunction - Search for a function by name (given the name) */
5112 /* in the set of all functions that are in a pBlock */
5113 /* (note - I expect this to change because I'm planning to limit */
5114 /* pBlock's to just one function declaration */
5115 /*-----------------------------------------------------------------*/
5116 pCode *findFunction(char *fname)
5123 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5125 pc = setFirstItem(pb->function_entries);
5128 if((pc->type == PC_FUNCTION) &&
5130 (strcmp(fname, PCF(pc)->fname)==0))
5133 pc = setNextItem(pb->function_entries);
5141 void MarkUsedRegisters(set *regset)
5146 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5147 r2 = pic14_regWithIdx(r1->rIdx);
5153 void pBlockStats(FILE *of, pBlock *pb)
5159 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5161 // for now just print the first element of each set
5162 pc = setFirstItem(pb->function_entries);
5164 fprintf(of,";entry: ");
5167 pc = setFirstItem(pb->function_exits);
5169 fprintf(of,";has an exit\n");
5173 pc = setFirstItem(pb->function_calls);
5175 fprintf(of,";functions called:\n");
5178 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5179 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5181 pc = setNextItem(pb->function_calls);
5185 r = setFirstItem(pb->tregisters);
5187 int n = elementsInSet(pb->tregisters);
5189 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5192 fprintf(of,"; %s\n",r->name);
5193 r = setNextItem(pb->tregisters);
5198 /*-----------------------------------------------------------------*/
5199 /*-----------------------------------------------------------------*/
5201 static void sequencepCode(void)
5207 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5209 pb->seq = GpCodeSequenceNumber+1;
5211 for( pc = pb->pcHead; pc; pc = pc->next)
5212 pc->seq = ++GpCodeSequenceNumber;
5218 /*-----------------------------------------------------------------*/
5219 /*-----------------------------------------------------------------*/
5220 set *register_usage(pBlock *pb)
5223 set *registers=NULL;
5224 set *registersInCallPath = NULL;
5226 /* check recursion */
5228 pc = setFirstItem(pb->function_entries);
5235 if(pc->type != PC_FUNCTION)
5236 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5238 pc = setFirstItem(pb->function_calls);
5239 for( ; pc; pc = setNextItem(pb->function_calls)) {
5241 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5242 char *dest = get_op_from_instruction(PCI(pc));
5244 pcn = findFunction(dest);
5246 registersInCallPath = register_usage(pcn->pb);
5248 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5253 pBlockStats(stderr,pb); // debug
5256 // Mark the registers in this block as used.
5258 MarkUsedRegisters(pb->tregisters);
5259 if(registersInCallPath) {
5260 /* registers were used in the functions this pBlock has called */
5261 /* so now, we need to see if these collide with the ones we are */
5264 regs *r1,*r2, *newreg;
5266 DFPRINTF((stderr,"comparing registers\n"));
5268 r1 = setFirstItem(registersInCallPath);
5271 r2 = setFirstItem(pb->tregisters);
5273 while(r2 && (r1->type != REG_STK)) {
5275 if(r2->rIdx == r1->rIdx) {
5276 newreg = pic14_findFreeReg(REG_GPR);
5280 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5284 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5285 r1->rIdx, newreg->rIdx));
5286 r2->rIdx = newreg->rIdx;
5287 //if(r2->name) free(r2->name);
5289 r2->name = Safe_strdup(newreg->name);
5293 newreg->wasUsed = 1;
5295 r2 = setNextItem(pb->tregisters);
5298 r1 = setNextItem(registersInCallPath);
5301 /* Collisions have been resolved. Now free the registers in the call path */
5302 r1 = setFirstItem(registersInCallPath);
5304 if(r1->type != REG_STK) {
5305 newreg = pic14_regWithIdx(r1->rIdx);
5308 r1 = setNextItem(registersInCallPath);
5312 // MarkUsedRegisters(pb->registers);
5314 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5317 DFPRINTF((stderr,"returning regs\n"));
5319 DFPRINTF((stderr,"not returning regs\n"));
5321 DFPRINTF((stderr,"pBlock after register optim.\n"));
5322 pBlockStats(stderr,pb); // debug
5328 /*-----------------------------------------------------------------*/
5329 /* printCallTree - writes the call tree to a file */
5331 /*-----------------------------------------------------------------*/
5332 void pct2(FILE *of,pBlock *pb,int indent)
5336 // set *registersInCallPath = NULL;
5342 return; //recursion ?
5344 pc = setFirstItem(pb->function_entries);
5351 for(i=0;i<indent;i++) // Indentation
5354 if(pc->type == PC_FUNCTION)
5355 fprintf(of,"%s\n",PCF(pc)->fname);
5360 pc = setFirstItem(pb->function_calls);
5361 for( ; pc; pc = setNextItem(pb->function_calls)) {
5363 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5364 char *dest = get_op_from_instruction(PCI(pc));
5366 pcn = findFunction(dest);
5368 pct2(of,pcn->pb,indent+1);
5370 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5378 /*-----------------------------------------------------------------*/
5379 /* printCallTree - writes the call tree to a file */
5381 /*-----------------------------------------------------------------*/
5383 void printCallTree(FILE *of)
5395 fprintf(of, "\npBlock statistics\n");
5396 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5401 fprintf(of,"Call Tree\n");
5402 pbr = the_pFile->functions;
5406 if(!ispCodeFunction(pc))
5407 fprintf(of,"bug in call tree");
5410 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5412 while(pc->next && !ispCodeFunction(pc->next)) {
5414 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5415 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5423 fprintf(of,"\n**************\n\na better call tree\n");
5424 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5429 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5430 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5436 /*-----------------------------------------------------------------*/
5438 /*-----------------------------------------------------------------*/
5440 void InlineFunction(pBlock *pb)
5448 pc = setFirstItem(pb->function_calls);
5450 for( ; pc; pc = setNextItem(pb->function_calls)) {
5453 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5459 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5461 //fprintf(stderr,"Cool can inline:\n");
5462 //pcn->print(stderr,pcn);
5464 //fprintf(stderr,"recursive call Inline\n");
5465 InlineFunction(pcn->pb);
5466 //fprintf(stderr,"return from recursive call Inline\n");
5469 At this point, *pc points to a CALL mnemonic, and
5470 *pcn points to the function that is being called.
5472 To in-line this call, we need to remove the CALL
5473 and RETURN(s), and link the function pCode in with
5479 /* Remove the CALL */
5483 /* remove callee pBlock from the pBlock linked list */
5484 removepBlock(pcn->pb);
5492 /* Remove the Function pCode */
5493 pct = findNextInstruction(pcn->next);
5495 /* Link the function with the callee */
5496 pc->next = pcn->next;
5497 pcn->next->prev = pc;
5499 /* Convert the function name into a label */
5501 pbr = Safe_calloc(1,sizeof(pBranch));
5502 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5504 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5505 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5507 /* turn all of the return's except the last into goto's */
5508 /* check case for 2 instruction pBlocks */
5509 pce = findNextInstruction(pcn->next);
5511 pCode *pce_next = findNextInstruction(pce->next);
5513 if(pce_next == NULL) {
5514 /* found the last return */
5515 pCode *pc_call_next = findNextInstruction(pc_call->next);
5517 //fprintf(stderr,"found last return\n");
5518 //pce->print(stderr,pce);
5519 pce->prev->next = pc_call->next;
5520 pc_call->next->prev = pce->prev;
5521 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5531 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5537 /*-----------------------------------------------------------------*/
5539 /*-----------------------------------------------------------------*/
5541 void InlinepCode(void)
5550 if(!functionInlining)
5553 /* Loop through all of the function definitions and count the
5554 * number of times each one is called */
5555 //fprintf(stderr,"inlining %d\n",__LINE__);
5557 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5559 pc = setFirstItem(pb->function_calls);
5561 for( ; pc; pc = setNextItem(pb->function_calls)) {
5564 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5565 if(pcn && isPCF(pcn)) {
5566 PCF(pcn)->ncalled++;
5569 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5574 //fprintf(stderr,"inlining %d\n",__LINE__);
5576 /* Now, Loop through the function definitions again, but this
5577 * time inline those functions that have only been called once. */
5579 InlineFunction(the_pFile->pbHead);
5580 //fprintf(stderr,"inlining %d\n",__LINE__);
5582 for(pb = the_pFile->pbHead; pb; pb = pb->next)