1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
78 int debug_verbose = 0; /* Set true to inundate .asm file */
80 // static int GpCodeSequenceNumber = 1;
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(int level);
87 extern int picIsInitialized(void);
89 /****************************************************************/
90 /* Forward declarations */
91 /****************************************************************/
93 void unlinkpCode(pCode *pc);
95 static void genericAnalyze(pCode *pc);
96 static void AnalyzeGOTO(pCode *pc);
97 static void AnalyzeSKIP(pCode *pc);
98 static void AnalyzeRETURN(pCode *pc);
101 static void genericDestruct(pCode *pc);
102 static void genericPrint(FILE *of,pCode *pc);
104 static void pCodePrintLabel(FILE *of, pCode *pc);
105 static void pCodePrintFunction(FILE *of, pCode *pc);
106 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
107 static char *get_op_from_instruction( pCodeInstruction *pcc);
108 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
109 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
110 int pCodePeepMatchRule(pCode *pc);
111 void pBlockStats(FILE *of, pBlock *pb);
112 pBlock *newpBlock(void);
113 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
114 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
115 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
116 void pCodeRegMapLiveRanges(pBlock *pb);
119 /****************************************************************/
120 /* PIC Instructions */
121 /****************************************************************/
123 pCodeInstruction pciADDWF = {
124 {PC_OPCODE, NULL, NULL, 0, NULL,
137 1,0, // dest, bit instruction
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];
1203 /* This definition needs to be part of configure.in */
1204 // #define USE_VSNPRINTF
1206 #ifdef USE_VSNPRINTF
1207 // Alas, vsnprintf is not ANSI standard, and does not exist
1208 // on Solaris (and probably other non-Gnu flavored Unixes).
1210 /*-----------------------------------------------------------------*/
1211 /* SAFE_snprintf - like snprintf except the string pointer is */
1212 /* after the string has been printed to. This is */
1213 /* useful for printing to string as though if it */
1214 /* were a stream. */
1215 /*-----------------------------------------------------------------*/
1216 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1224 va_start(val, format);
1226 vsnprintf(*str, *size, format, val);
1232 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1233 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1241 #else // USE_VSNPRINTF
1243 // This version is *not* safe, despite the name.
1245 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1249 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1254 va_start(val, format);
1256 vsprintf(buffer, format, val);
1259 len = strlen(buffer);
1261 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1262 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1265 strcpy(*str, buffer);
1271 #endif // USE_VSNPRINTF
1274 extern void initStack(int base_address, int size);
1275 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1276 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1277 extern void init_pic(char *);
1279 void pCodeInitRegisters(void)
1281 static int initialized=0;
1287 initStack(0xfff, 8);
1288 init_pic(port->processor);
1290 pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
1291 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1292 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
1293 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1294 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1295 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1297 pc_status.rIdx = IDX_STATUS;
1298 pc_fsr.rIdx = IDX_FSR;
1299 pc_indf.rIdx = IDX_INDF;
1300 pc_intcon.rIdx = IDX_INTCON;
1301 pc_pcl.rIdx = IDX_PCL;
1302 pc_pclath.rIdx = IDX_PCLATH;
1304 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1305 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1306 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1308 pc_kzero.rIdx = IDX_KZ;
1309 pc_wsave.rIdx = IDX_WSAVE;
1310 pc_ssave.rIdx = IDX_SSAVE;
1312 /* probably should put this in a separate initialization routine */
1313 pb_dead_pcodes = newpBlock();
1317 /*-----------------------------------------------------------------*/
1318 /* mnem2key - convert a pic mnemonic into a hash key */
1319 /* (BTW - this spreads the mnemonics quite well) */
1321 /*-----------------------------------------------------------------*/
1323 int mnem2key(char const *mnem)
1332 key += toupper(*mnem++) +1;
1336 return (key & 0x1f);
1340 void pic14initMnemonics(void)
1345 pCodeInstruction *pci;
1347 if(mnemonics_initialized)
1350 //FIXME - probably should NULL out the array before making the assignments
1351 //since we check the array contents below this initialization.
1353 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1354 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1355 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1356 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1357 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1358 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1359 pic14Mnemonics[POC_BCF] = &pciBCF;
1360 pic14Mnemonics[POC_BSF] = &pciBSF;
1361 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1362 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1363 pic14Mnemonics[POC_CALL] = &pciCALL;
1364 pic14Mnemonics[POC_COMF] = &pciCOMF;
1365 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1366 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1367 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1368 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1369 pic14Mnemonics[POC_DECF] = &pciDECF;
1370 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1371 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1372 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1373 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1374 pic14Mnemonics[POC_INCF] = &pciINCF;
1375 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1376 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1377 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1378 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1379 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1380 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1381 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1382 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1383 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1384 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1385 pic14Mnemonics[POC_NOP] = &pciNOP;
1386 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1387 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1388 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1389 pic14Mnemonics[POC_RLF] = &pciRLF;
1390 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1391 pic14Mnemonics[POC_RRF] = &pciRRF;
1392 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1393 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1394 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1395 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1396 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1397 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1398 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1399 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1400 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1401 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1403 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1404 if(pic14Mnemonics[i])
1405 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1406 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1409 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1410 pci = hTabNextItem(pic14MnemonicsHash, &key);
1413 mnemonics_initialized = 1;
1416 int getpCodePeepCommand(char *cmd);
1418 int getpCode(char *mnem,unsigned dest)
1421 pCodeInstruction *pci;
1422 int key = mnem2key(mnem);
1424 if(!mnemonics_initialized)
1425 pic14initMnemonics();
1427 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1431 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1432 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1436 pci = hTabNextItemWK (pic14MnemonicsHash);
1443 /*-----------------------------------------------------------------*
1444 * pic14initpCodePeepCommands
1446 *-----------------------------------------------------------------*/
1447 void pic14initpCodePeepCommands(void)
1455 hTabAddItem(&pic14pCodePeepCommandsHash,
1456 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1458 } while (peepCommands[i].cmd);
1460 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1463 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1464 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1469 /*-----------------------------------------------------------------
1472 *-----------------------------------------------------------------*/
1474 int getpCodePeepCommand(char *cmd)
1478 int key = mnem2key(cmd);
1481 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1484 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1485 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1489 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1496 char getpBlock_dbName(pBlock *pb)
1502 return pb->cmemmap->dbName;
1506 void pBlockConvert2ISR(pBlock *pb)
1517 /*-----------------------------------------------------------------*/
1518 /* movepBlock2Head - given the dbname of a pBlock, move all */
1519 /* instances to the front of the doubly linked */
1520 /* list of pBlocks */
1521 /*-----------------------------------------------------------------*/
1523 void movepBlock2Head(char dbName)
1527 pb = the_pFile->pbHead;
1531 if(getpBlock_dbName(pb) == dbName) {
1532 pBlock *pbn = pb->next;
1533 pb->next = the_pFile->pbHead;
1534 the_pFile->pbHead->prev = pb;
1535 the_pFile->pbHead = pb;
1538 pb->prev->next = pbn;
1540 // If the pBlock that we just moved was the last
1541 // one in the link of all of the pBlocks, then we
1542 // need to point the tail to the block just before
1543 // the one we moved.
1544 // Note: if pb->next is NULL, then pb must have
1545 // been the last pBlock in the chain.
1548 pbn->prev = pb->prev;
1550 the_pFile->pbTail = pb->prev;
1561 void copypCode(FILE *of, char dbName)
1565 if(!of || !the_pFile)
1568 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1569 if(getpBlock_dbName(pb) == dbName) {
1576 void pcode_test(void)
1579 DFPRINTF((stderr,"pcode is alive!\n"));
1589 /* create the file name */
1590 strcpy(buffer,srcFileName);
1591 strcat(buffer,".p");
1593 if( !(pFile = fopen(buffer, "w" ))) {
1594 werror(E_FILE_OPEN_ERR,buffer);
1598 fprintf(pFile,"pcode dump\n\n");
1600 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1601 fprintf(pFile,"\n\tNew pBlock\n\n");
1603 fprintf(pFile,"%s",pb->cmemmap->sname);
1605 fprintf(pFile,"internal pblock");
1607 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1608 printpBlock(pFile,pb);
1612 /*-----------------------------------------------------------------*/
1613 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1614 /* ister, RegCond will return the bit being referenced. */
1616 /* fixme - why not just OR in the pcop bit field */
1617 /*-----------------------------------------------------------------*/
1619 static int RegCond(pCodeOp *pcop)
1625 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1626 switch(PCORB(pcop)->bit) {
1640 /*-----------------------------------------------------------------*/
1641 /* newpCode - create and return a newly initialized pCode */
1643 /* fixme - rename this */
1645 /* The purpose of this routine is to create a new Instruction */
1646 /* pCode. This is called by gen.c while the assembly code is being */
1650 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1651 /* (note that the op is analogous to but not the */
1652 /* same thing as the opcode of the instruction.) */
1653 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1656 /* a pointer to the new malloc'd pCode is returned. */
1660 /*-----------------------------------------------------------------*/
1661 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1663 pCodeInstruction *pci ;
1665 if(!mnemonics_initialized)
1666 pic14initMnemonics();
1668 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1670 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1671 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1674 if(pci->inCond & PCC_EXAMINE_PCOP)
1675 pci->inCond |= RegCond(pcop);
1677 if(pci->outCond & PCC_EXAMINE_PCOP)
1678 pci->outCond |= RegCond(pcop);
1680 pci->pc.prev = pci->pc.next = NULL;
1681 return (pCode *)pci;
1684 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1690 /*-----------------------------------------------------------------*/
1691 /* newpCodeWild - create a "wild" as in wild card pCode */
1693 /* Wild pcodes are used during the peep hole optimizer to serve */
1694 /* as place holders for any instruction. When a snippet of code is */
1695 /* compared to a peep hole rule, the wild card opcode will match */
1696 /* any instruction. However, the optional operand and label are */
1697 /* additional qualifiers that must also be matched before the */
1698 /* line (of assembly code) is declared matched. Note that the */
1699 /* operand may be wild too. */
1701 /* Note, a wild instruction is specified just like a wild var: */
1702 /* %4 ; A wild instruction, */
1703 /* See the peeph.def file for additional examples */
1705 /*-----------------------------------------------------------------*/
1707 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1712 pcw = Safe_calloc(1,sizeof(pCodeWild));
1714 pcw->pci.pc.type = PC_WILD;
1715 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1716 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1717 pcw->pci.pc.pb = NULL;
1719 // pcw->pci.pc.analyze = genericAnalyze;
1720 pcw->pci.pc.destruct = genericDestruct;
1721 pcw->pci.pc.print = genericPrint;
1723 pcw->id = pCodeID; // this is the 'n' in %n
1724 pcw->operand = optional_operand;
1725 pcw->label = optional_label;
1727 pcw->mustBeBitSkipInst = 0;
1728 pcw->mustNotBeBitSkipInst = 0;
1729 pcw->invertBitSkipInst = 0;
1731 return ( (pCode *)pcw);
1735 /*-----------------------------------------------------------------*/
1736 /* newPcodeInlineP - create a new pCode from a char string */
1737 /*-----------------------------------------------------------------*/
1740 pCode *newpCodeInlineP(char *cP)
1745 pcc = Safe_calloc(1,sizeof(pCodeComment));
1747 pcc->pc.type = PC_INLINE;
1748 pcc->pc.prev = pcc->pc.next = NULL;
1749 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1752 // pcc->pc.analyze = genericAnalyze;
1753 pcc->pc.destruct = genericDestruct;
1754 pcc->pc.print = genericPrint;
1757 pcc->comment = Safe_strdup(cP);
1759 pcc->comment = NULL;
1761 return ( (pCode *)pcc);
1765 /*-----------------------------------------------------------------*/
1766 /* newPcodeCharP - create a new pCode from a char string */
1767 /*-----------------------------------------------------------------*/
1769 pCode *newpCodeCharP(char *cP)
1774 pcc = Safe_calloc(1,sizeof(pCodeComment));
1776 pcc->pc.type = PC_COMMENT;
1777 pcc->pc.prev = pcc->pc.next = NULL;
1778 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1781 // pcc->pc.analyze = genericAnalyze;
1782 pcc->pc.destruct = genericDestruct;
1783 pcc->pc.print = genericPrint;
1786 pcc->comment = Safe_strdup(cP);
1788 pcc->comment = NULL;
1790 return ( (pCode *)pcc);
1794 /*-----------------------------------------------------------------*/
1795 /* newpCodeFunction - */
1796 /*-----------------------------------------------------------------*/
1799 pCode *newpCodeFunction(char *mod,char *f)
1803 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1804 //_ALLOC(pcf,sizeof(pCodeFunction));
1806 pcf->pc.type = PC_FUNCTION;
1807 pcf->pc.prev = pcf->pc.next = NULL;
1808 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1811 // pcf->pc.analyze = genericAnalyze;
1812 pcf->pc.destruct = genericDestruct;
1813 pcf->pc.print = pCodePrintFunction;
1818 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1819 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1820 strcpy(pcf->modname,mod);
1822 pcf->modname = NULL;
1825 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1826 pcf->fname = Safe_calloc(1,strlen(f)+1);
1827 strcpy(pcf->fname,f);
1831 return ( (pCode *)pcf);
1835 /*-----------------------------------------------------------------*/
1837 /*-----------------------------------------------------------------*/
1838 void destructpCodeFlow(pCode *pc)
1840 if(!pc || !isPCFL(pc))
1849 deleteSet(&PCFL(pc)->registers);
1850 deleteSet(&PCFL(pc)->from);
1851 deleteSet(&PCFL(pc)->to);
1856 pCode *newpCodeFlow(void )
1860 //_ALLOC(pcflow,sizeof(pCodeFlow));
1861 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1863 pcflow->pc.type = PC_FLOW;
1864 pcflow->pc.prev = pcflow->pc.next = NULL;
1865 pcflow->pc.pb = NULL;
1867 // pcflow->pc.analyze = genericAnalyze;
1868 pcflow->pc.destruct = destructpCodeFlow;
1869 pcflow->pc.print = genericPrint;
1871 pcflow->pc.seq = GpcFlowSeq++;
1873 pcflow->from = pcflow->to = NULL;
1875 pcflow->inCond = PCC_NONE;
1876 pcflow->outCond = PCC_NONE;
1878 pcflow->firstBank = -1;
1879 pcflow->lastBank = -1;
1881 pcflow->FromConflicts = 0;
1882 pcflow->ToConflicts = 0;
1886 pcflow->registers = newSet();
1888 return ( (pCode *)pcflow);
1892 /*-----------------------------------------------------------------*/
1893 /*-----------------------------------------------------------------*/
1894 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1896 pCodeFlowLink *pcflowLink;
1898 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1900 pcflowLink->pcflow = pcflow;
1901 pcflowLink->bank_conflict = 0;
1906 /*-----------------------------------------------------------------*/
1907 /* newpCodeCSource - create a new pCode Source Symbol */
1908 /*-----------------------------------------------------------------*/
1910 pCode *newpCodeCSource(int ln, char *f, char *l)
1915 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1917 pccs->pc.type = PC_CSOURCE;
1918 pccs->pc.prev = pccs->pc.next = NULL;
1921 pccs->pc.destruct = genericDestruct;
1922 pccs->pc.print = genericPrint;
1924 pccs->line_number = ln;
1926 pccs->line = Safe_strdup(l);
1931 pccs->file_name = Safe_strdup(f);
1933 pccs->file_name = NULL;
1935 return ( (pCode *)pccs);
1938 /*-----------------------------------------------------------------*/
1939 /* pCodeLabelDestruct - free memory used by a label. */
1940 /*-----------------------------------------------------------------*/
1941 static void pCodeLabelDestruct(pCode *pc)
1947 if((pc->type == PC_LABEL) && PCL(pc)->label)
1948 free(PCL(pc)->label);
1954 pCode *newpCodeLabel(char *name, int key)
1960 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1962 pcl->pc.type = PC_LABEL;
1963 pcl->pc.prev = pcl->pc.next = NULL;
1964 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1967 // pcl->pc.analyze = genericAnalyze;
1968 pcl->pc.destruct = pCodeLabelDestruct;
1969 pcl->pc.print = pCodePrintLabel;
1975 sprintf(s,"_%05d_DS_",key);
1980 pcl->label = Safe_strdup(s);
1982 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1983 return ( (pCode *)pcl);
1988 /*-----------------------------------------------------------------*/
1989 /* newpBlock - create and return a pointer to a new pBlock */
1990 /*-----------------------------------------------------------------*/
1991 pBlock *newpBlock(void)
1996 PpB = Safe_calloc(1,sizeof(pBlock) );
1997 PpB->next = PpB->prev = NULL;
1999 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2000 PpB->tregisters = NULL;
2002 PpB->FlowTree = NULL;
2008 /*-----------------------------------------------------------------*/
2009 /* newpCodeChain - create a new chain of pCodes */
2010 /*-----------------------------------------------------------------*
2012 * This function will create a new pBlock and the pointer to the
2013 * pCode that is passed in will be the first pCode in the block.
2014 *-----------------------------------------------------------------*/
2017 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2020 pBlock *pB = newpBlock();
2022 pB->pcHead = pB->pcTail = pc;
2029 /*-----------------------------------------------------------------*/
2030 /* newpCodeOpLabel - Create a new label given the key */
2031 /* Note, a negative key means that the label is part of wild card */
2032 /* (and hence a wild card label) used in the pCodePeep */
2033 /* optimizations). */
2034 /*-----------------------------------------------------------------*/
2036 pCodeOp *newpCodeOpLabel(char *name, int key)
2039 static int label_key=-1;
2043 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2044 pcop->type = PO_LABEL;
2049 sprintf(s=buffer,"_%05d_DS_",key);
2051 s = name, key = label_key--;
2054 pcop->name = Safe_strdup(s);
2056 ((pCodeOpLabel *)pcop)->key = key;
2058 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2062 /*-----------------------------------------------------------------*/
2063 /*-----------------------------------------------------------------*/
2064 pCodeOp *newpCodeOpLit(int lit)
2070 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2071 pcop->type = PO_LITERAL;
2075 sprintf(s,"0x%02x",lit);
2077 pcop->name = Safe_strdup(s);
2080 ((pCodeOpLit *)pcop)->lit = lit;
2085 /*-----------------------------------------------------------------*/
2086 /*-----------------------------------------------------------------*/
2087 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2091 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2092 pcop->type = PO_IMMEDIATE;
2094 regs *r = dirregWithName(name);
2095 pcop->name = Safe_strdup(name);
2098 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2099 PCOI(pcop)->rIdx = r->rIdx;
2101 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2102 PCOI(pcop)->rIdx = -1;
2104 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2109 PCOI(pcop)->index = index;
2110 PCOI(pcop)->offset = offset;
2111 PCOI(pcop)->_const = code_space;
2116 /*-----------------------------------------------------------------*/
2117 /*-----------------------------------------------------------------*/
2118 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2124 if(!pcwb || !subtype) {
2125 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2129 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2130 pcop->type = PO_WILD;
2131 sprintf(s,"%%%d",id);
2132 pcop->name = Safe_strdup(s);
2134 PCOW(pcop)->id = id;
2135 PCOW(pcop)->pcwb = pcwb;
2136 PCOW(pcop)->subtype = subtype;
2137 PCOW(pcop)->matched = NULL;
2142 /*-----------------------------------------------------------------*/
2143 /*-----------------------------------------------------------------*/
2144 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2148 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2149 pcop->type = PO_GPR_BIT;
2151 pcop->name = Safe_strdup(s);
2155 PCORB(pcop)->bit = bit;
2156 PCORB(pcop)->inBitSpace = inBitSpace;
2158 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2159 PCOR(pcop)->r = NULL;
2160 PCOR(pcop)->rIdx = 0;
2164 /*-----------------------------------------------------------------*
2165 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2167 * If rIdx >=0 then a specific register from the set of registers
2168 * will be selected. If rIdx <0, then a new register will be searched
2170 *-----------------------------------------------------------------*/
2172 pCodeOp *newpCodeOpReg(int rIdx)
2176 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2181 PCOR(pcop)->rIdx = rIdx;
2182 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2184 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2187 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2190 pcop->type = PCOR(pcop)->r->pc_type;
2195 pCodeOp *newpCodeOpRegFromStr(char *name)
2199 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2200 PCOR(pcop)->r = allocRegByName(name, 1);
2201 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2202 pcop->type = PCOR(pcop)->r->pc_type;
2203 pcop->name = PCOR(pcop)->r->name;
2208 /*-----------------------------------------------------------------*/
2209 /*-----------------------------------------------------------------*/
2211 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2218 pcop = newpCodeOpBit(name, -1,0);
2222 pcop = newpCodeOpLit(-1);
2226 pcop = newpCodeOpLabel(NULL,-1);
2229 pcop = newpCodeOpReg(-1);
2232 case PO_GPR_REGISTER:
2234 pcop = newpCodeOpRegFromStr(name);
2236 pcop = newpCodeOpReg(-1);
2240 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2243 pcop->name = Safe_strdup(name);
2251 /*-----------------------------------------------------------------*/
2252 /*-----------------------------------------------------------------*/
2253 void pCodeConstString(char *name, char *value)
2257 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2262 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2266 sprintf(buffer,"; %s = %s",name,value);
2268 addpCode2pBlock(pb,newpCodeCharP(buffer));
2269 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2272 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2278 /*-----------------------------------------------------------------*/
2279 /*-----------------------------------------------------------------*/
2280 void pCodeReadCodeTable(void)
2284 fprintf(stderr, " %s\n",__FUNCTION__);
2286 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2290 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2291 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2292 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2293 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2295 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2296 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2297 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2298 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2303 /*-----------------------------------------------------------------*/
2304 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2305 /*-----------------------------------------------------------------*/
2306 void addpCode2pBlock(pBlock *pb, pCode *pc)
2313 /* If this is the first pcode to be added to a block that
2314 * was initialized with a NULL pcode, then go ahead and
2315 * make this pcode the head and tail */
2316 pb->pcHead = pb->pcTail = pc;
2319 pb->pcTail->next = pc;
2321 pc->prev = pb->pcTail;
2328 /*-----------------------------------------------------------------*/
2329 /* addpBlock - place a pBlock into the pFile */
2330 /*-----------------------------------------------------------------*/
2331 void addpBlock(pBlock *pb)
2333 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2336 /* First time called, we'll pass through here. */
2337 //_ALLOC(the_pFile,sizeof(pFile));
2338 the_pFile = Safe_calloc(1,sizeof(pFile));
2339 the_pFile->pbHead = the_pFile->pbTail = pb;
2340 the_pFile->functions = NULL;
2344 the_pFile->pbTail->next = pb;
2345 pb->prev = the_pFile->pbTail;
2347 the_pFile->pbTail = pb;
2350 /*-----------------------------------------------------------------*/
2351 /* removepBlock - remove a pBlock from the pFile */
2352 /*-----------------------------------------------------------------*/
2353 void removepBlock(pBlock *pb)
2361 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2363 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2366 if(pbs == the_pFile->pbHead)
2367 the_pFile->pbHead = pbs->next;
2369 if (pbs == the_pFile->pbTail)
2370 the_pFile->pbTail = pbs->prev;
2373 pbs->next->prev = pbs->prev;
2376 pbs->prev->next = pbs->next;
2383 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2387 /*-----------------------------------------------------------------*/
2388 /* printpCode - write the contents of a pCode to a file */
2389 /*-----------------------------------------------------------------*/
2390 void printpCode(FILE *of, pCode *pc)
2401 fprintf(of,"warning - unable to print pCode\n");
2404 /*-----------------------------------------------------------------*/
2405 /* printpBlock - write the contents of a pBlock to a file */
2406 /*-----------------------------------------------------------------*/
2407 void printpBlock(FILE *of, pBlock *pb)
2417 for(pc = pb->pcHead; pc; pc = pc->next)
2422 /*-----------------------------------------------------------------*/
2424 /* pCode processing */
2428 /*-----------------------------------------------------------------*/
2430 void unlinkpCode(pCode *pc)
2436 fprintf(stderr,"Unlinking: ");
2437 printpCode(stderr, pc);
2440 pc->prev->next = pc->next;
2442 pc->next->prev = pc->prev;
2444 pc->prev = pc->next = NULL;
2448 /*-----------------------------------------------------------------*/
2449 /*-----------------------------------------------------------------*/
2451 static void genericDestruct(pCode *pc)
2457 /* For instructions, tell the register (if there's one used)
2458 * that it's no longer needed */
2459 regs *reg = getRegFromInstruction(pc);
2461 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2464 /* Instead of deleting the memory used by this pCode, mark
2465 * the object as bad so that if there's a pointer to this pCode
2466 * dangling around somewhere then (hopefully) when the type is
2467 * checked we'll catch it.
2472 addpCode2pBlock(pb_dead_pcodes, pc);
2479 /*-----------------------------------------------------------------*/
2480 /*-----------------------------------------------------------------*/
2481 void pBlockRegs(FILE *of, pBlock *pb)
2486 r = setFirstItem(pb->tregisters);
2488 r = setNextItem(pb->tregisters);
2493 /*-----------------------------------------------------------------*/
2494 /*-----------------------------------------------------------------*/
2495 char *get_op(pCodeOp *pcop,char *buffer, int size)
2500 int use_buffer = 1; // copy the string to the passed buffer pointer
2505 use_buffer = 0; // Don't bother copying the string to the buffer.
2509 switch(pcop->type) {
2513 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2516 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 return ("ERROR Null: "__FUNCTION__);
2597 /*-----------------------------------------------------------------*/
2598 /*-----------------------------------------------------------------*/
2599 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2602 fprintf(of,"pcodeopprint- not implemented\n");
2605 /*-----------------------------------------------------------------*/
2606 /*-----------------------------------------------------------------*/
2607 char *pCode2str(char *str, int size, pCode *pc)
2615 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2617 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2619 if(PCI(pc)->isBitInst) {
2620 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2621 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2622 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2623 PCI(pc)->pcop->name ,
2624 PCI(pc)->pcop->name );
2626 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2627 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2628 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2629 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2631 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2632 //PCI(pc)->pcop->t.bit );
2635 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2636 if( PCI(pc)->num_ops == 2)
2637 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2639 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2642 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2644 if( PCI(pc)->num_ops == 2)
2645 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2653 /* assuming that comment ends with a \n */
2654 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2658 /* assuming that inline code ends with a \n */
2659 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2663 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2666 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2669 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2672 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2675 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2679 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2686 /*-----------------------------------------------------------------*/
2687 /* genericPrint - the contents of a pCode to a file */
2688 /*-----------------------------------------------------------------*/
2689 static void genericPrint(FILE *of, pCode *pc)
2697 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2701 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2705 // If the opcode has a label, print that first
2707 pBranch *pbl = PCI(pc)->label;
2708 while(pbl && pbl->pc) {
2709 if(pbl->pc->type == PC_LABEL)
2710 pCodePrintLabel(of, pbl->pc);
2716 genericPrint(of,PCODE(PCI(pc)->cline));
2721 pCode2str(str, 256, pc);
2723 fprintf(of,"%s",str);
2727 fprintf(of, "\t;key=%03x",pc->seq);
2729 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2734 pBranch *dpb = pc->to; // debug
2736 switch ( dpb->pc->type) {
2738 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2741 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2744 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2747 fprintf(of, "\t;flow");
2761 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2762 if(PCW(pc)->pci.label)
2763 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2765 if(PCW(pc)->operand) {
2766 fprintf(of,";\toperand ");
2767 pCodeOpPrint(of,PCW(pc)->operand );
2773 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2774 if(PCFL(pc)->ancestor)
2775 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2782 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2786 fprintf(of,"unknown pCode type %d\n",pc->type);
2791 /*-----------------------------------------------------------------*/
2792 /* pCodePrintFunction - prints function begin/end */
2793 /*-----------------------------------------------------------------*/
2795 static void pCodePrintFunction(FILE *of, pCode *pc)
2801 if( ((pCodeFunction *)pc)->modname)
2802 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2804 if(PCF(pc)->fname) {
2805 pBranch *exits = PCF(pc)->to;
2807 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2810 exits = exits->next;
2813 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2816 if((PCF(pc)->from &&
2817 PCF(pc)->from->pc->type == PC_FUNCTION &&
2818 PCF(PCF(pc)->from->pc)->fname) )
2819 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2821 fprintf(of,"; exit point [can't find entry point]\n");
2824 /*-----------------------------------------------------------------*/
2825 /* pCodePrintLabel - prints label */
2826 /*-----------------------------------------------------------------*/
2828 static void pCodePrintLabel(FILE *of, pCode *pc)
2835 fprintf(of,"%s\n",PCL(pc)->label);
2836 else if (PCL(pc)->key >=0)
2837 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2839 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2842 /*-----------------------------------------------------------------*/
2843 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2844 /* remove it if it is found. */
2845 /*-----------------------------------------------------------------*/
2846 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2853 if(pcl->type == PC_OPCODE)
2854 b = PCI(pcl)->label;
2856 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2861 //fprintf (stderr, "%s \n",__FUNCTION__);
2862 //pcl->print(stderr,pcl);
2863 //pc->print(stderr,pc);
2866 //fprintf (stderr, "found label\n");
2870 bprev->next = b->next; /* Not first pCode in chain */
2874 PCI(pcl)->label = b->next; /* First pCode in chain */
2877 return; /* A label can't occur more than once */
2885 /*-----------------------------------------------------------------*/
2886 /*-----------------------------------------------------------------*/
2887 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2906 /*-----------------------------------------------------------------*/
2907 /* pBranchLink - given two pcodes, this function will link them */
2908 /* together through their pBranches */
2909 /*-----------------------------------------------------------------*/
2910 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2914 // Declare a new branch object for the 'from' pCode.
2916 //_ALLOC(b,sizeof(pBranch));
2917 b = Safe_calloc(1,sizeof(pBranch));
2918 b->pc = PCODE(t); // The link to the 'to' pCode.
2921 f->to = pBranchAppend(f->to,b);
2923 // Now do the same for the 'to' pCode.
2925 //_ALLOC(b,sizeof(pBranch));
2926 b = Safe_calloc(1,sizeof(pBranch));
2930 t->from = pBranchAppend(t->from,b);
2935 /*-----------------------------------------------------------------*/
2936 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2938 /*-----------------------------------------------------------------*/
2939 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2952 /*-----------------------------------------------------------------*/
2953 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2954 /*-----------------------------------------------------------------*/
2955 static void pCodeUnlink(pCode *pc)
2960 if(!pc->prev || !pc->next) {
2961 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2965 /* first remove the pCode from the chain */
2966 pc->prev->next = pc->next;
2967 pc->next->prev = pc->prev;
2969 /* Now for the hard part... */
2971 /* Remove the branches */
2975 pc1 = pb1->pc; /* Get the pCode that branches to the
2976 * one we're unlinking */
2978 /* search for the link back to this pCode (the one we're
2980 if(pb2 = pBranchFind(pc1->to,pc)) {
2981 pb2->pc = pc->to->pc; // make the replacement
2983 /* if the pCode we're unlinking contains multiple 'to'
2984 * branches (e.g. this a skip instruction) then we need
2985 * to copy these extra branches to the chain. */
2987 pBranchAppend(pb2, pc->to->next);
2996 /*-----------------------------------------------------------------*/
2997 /*-----------------------------------------------------------------*/
2999 static void genericAnalyze(pCode *pc)
3009 // Go through the pCodes that are in pCode chain and link
3010 // them together through the pBranches. Note, the pCodes
3011 // are linked together as a contiguous stream like the
3012 // assembly source code lines. The linking here mimics this
3013 // except that comments are not linked in.
3015 pCode *npc = pc->next;
3017 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3018 pBranchLink(pc,npc);
3023 /* reached the end of the pcode chain without finding
3024 * an instruction we could link to. */
3028 fprintf(stderr,"analyze PC_FLOW\n");
3032 fprintf(stderr,,";A bad pCode is being used\n");
3038 /*-----------------------------------------------------------------*/
3039 /*-----------------------------------------------------------------*/
3040 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3044 if(pc->type == PC_LABEL) {
3045 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3048 if(pc->type == PC_OPCODE) {
3049 pbr = PCI(pc)->label;
3051 if(pbr->pc->type == PC_LABEL) {
3052 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3062 /*-----------------------------------------------------------------*/
3063 /*-----------------------------------------------------------------*/
3064 int checkLabel(pCode *pc)
3068 if(pc && isPCI(pc)) {
3069 pbr = PCI(pc)->label;
3071 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3081 /*-----------------------------------------------------------------*/
3082 /* findLabelinpBlock - Search the pCode for a particular label */
3083 /*-----------------------------------------------------------------*/
3084 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3091 for(pc = pb->pcHead; pc; pc = pc->next)
3092 if(compareLabel(pc,pcop_label))
3098 /*-----------------------------------------------------------------*/
3099 /* findLabel - Search the pCode for a particular label */
3100 /*-----------------------------------------------------------------*/
3101 pCode * findLabel(pCodeOpLabel *pcop_label)
3109 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3110 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3114 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3118 /*-----------------------------------------------------------------*/
3119 /* findNextpCode - given a pCode, find the next of type 'pct' */
3120 /* in the linked list */
3121 /*-----------------------------------------------------------------*/
3122 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3135 /*-----------------------------------------------------------------*/
3136 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3137 /* in the linked list */
3138 /*-----------------------------------------------------------------*/
3139 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3151 /*-----------------------------------------------------------------*/
3152 /* findNextInstruction - given a pCode, find the next instruction */
3153 /* in the linked list */
3154 /*-----------------------------------------------------------------*/
3155 pCode * findNextInstruction(pCode *pci)
3160 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3164 fprintf(stderr,"findNextInstruction: ");
3165 printpCode(stderr, pc);
3170 //fprintf(stderr,"Couldn't find instruction\n");
3174 /*-----------------------------------------------------------------*/
3175 /* findNextInstruction - given a pCode, find the next instruction */
3176 /* in the linked list */
3177 /*-----------------------------------------------------------------*/
3178 pCode * findPrevInstruction(pCode *pci)
3180 return findPrevpCode(pci, PC_OPCODE);
3183 /*-----------------------------------------------------------------*/
3184 /* findFunctionEnd - given a pCode find the end of the function */
3185 /* that contains it */
3186 /*-----------------------------------------------------------------*/
3187 pCode * findFunctionEnd(pCode *pc)
3191 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3197 fprintf(stderr,"Couldn't find function end\n");
3202 /*-----------------------------------------------------------------*/
3203 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3204 /* instruction with which it is associated. */
3205 /*-----------------------------------------------------------------*/
3206 static void AnalyzeLabel(pCode *pc)
3215 static void AnalyzeGOTO(pCode *pc)
3218 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3222 static void AnalyzeSKIP(pCode *pc)
3225 pBranchLink(pc,findNextInstruction(pc->next));
3226 pBranchLink(pc,findNextInstruction(pc->next->next));
3230 static void AnalyzeRETURN(pCode *pc)
3233 // branch_link(pc,findFunctionEnd(pc->next));
3239 /*-----------------------------------------------------------------*/
3240 /*-----------------------------------------------------------------*/
3241 regs * getRegFromInstruction(pCode *pc)
3247 PCI(pc)->num_ops == 0 )
3250 switch(PCI(pc)->pcop->type) {
3253 return PCOR(PCI(pc)->pcop)->r;
3255 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3259 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3260 return PCOR(PCI(pc)->pcop)->r;
3263 if(PCOI(PCI(pc)->pcop)->r)
3264 return (PCOI(PCI(pc)->pcop)->r);
3266 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3267 return dirregWithName(PCI(pc)->pcop->name);
3268 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3271 return PCOR(PCI(pc)->pcop)->r;
3274 //fprintf(stderr, "getRegFromInstruction - dir\n");
3275 return PCOR(PCI(pc)->pcop)->r;
3277 //fprintf(stderr, "getRegFromInstruction - literal\n");
3281 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3282 //genericPrint(stderr, pc);
3290 /*-----------------------------------------------------------------*/
3291 /*-----------------------------------------------------------------*/
3293 void AnalyzepBlock(pBlock *pb)
3300 /* Find all of the registers used in this pBlock
3301 * by looking at each instruction and examining it's
3304 for(pc = pb->pcHead; pc; pc = pc->next) {
3306 /* Is this an instruction with operands? */
3307 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3309 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3311 /* Loop through all of the registers declared so far in
3312 this block and see if we find this one there */
3314 regs *r = setFirstItem(pb->tregisters);
3317 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3318 PCOR(PCI(pc)->pcop)->r = r;
3321 r = setNextItem(pb->tregisters);
3325 /* register wasn't found */
3326 //r = Safe_calloc(1, sizeof(regs));
3327 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3328 //addSet(&pb->tregisters, r);
3329 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3330 //PCOR(PCI(pc)->pcop)->r = r;
3331 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3333 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3336 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3337 if(PCOR(PCI(pc)->pcop)->r) {
3338 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3339 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3341 if(PCI(pc)->pcop->name)
3342 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3344 fprintf(stderr,"ERROR: NULL register\n");
3353 /*-----------------------------------------------------------------*/
3355 /*-----------------------------------------------------------------*/
3356 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3358 void InsertpFlow(pCode *pc, pCode **pflow)
3361 PCFL(*pflow)->end = pc;
3363 if(!pc || !pc->next)
3366 *pflow = newpCodeFlow();
3367 pCodeInsertAfter(pc, *pflow);
3370 /*-----------------------------------------------------------------*/
3371 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3372 /* the flow blocks. */
3374 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3375 * point the instruction flow changes.
3377 /*-----------------------------------------------------------------*/
3378 void BuildFlow(pBlock *pb)
3381 pCode *last_pci=NULL;
3388 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3389 /* Insert a pCodeFlow object at the beginning of a pBlock */
3391 InsertpFlow(pb->pcHead, &pflow);
3393 //pflow = newpCodeFlow(); /* Create a new Flow object */
3394 //pflow->next = pb->pcHead; /* Make the current head the next object */
3395 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3396 //pb->pcHead = pflow; /* Make the Flow object the head */
3399 for( pc = findNextInstruction(pb->pcHead);
3401 pc=findNextInstruction(pc)) {
3404 PCI(pc)->pcflow = PCFL(pflow);
3406 //fprintf(stderr," build: ");
3407 //pflow->print(stderr,pflow);
3409 if( PCI(pc)->isSkip) {
3411 /* The two instructions immediately following this one
3412 * mark the beginning of a new flow segment */
3414 while(pc && PCI(pc)->isSkip) {
3416 PCI(pc)->pcflow = PCFL(pflow);
3420 InsertpFlow(pc, &pflow);
3421 pc=findNextInstruction(pc->next);
3429 PCI(pc)->pcflow = PCFL(pflow);
3431 InsertpFlow(pc, &pflow);
3433 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3435 InsertpFlow(pc, &pflow);
3438 } else if (checkLabel(pc)) {
3440 /* This instruction marks the beginning of a
3441 * new flow segment */
3446 /* If the previous pCode is not a flow object, then
3447 * insert a new flow object. (This check prevents
3448 * two consecutive flow objects from being insert in
3449 * the case where a skip instruction preceeds an
3450 * instruction containing a label.) */
3452 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3453 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3455 PCI(pc)->pcflow = PCFL(pflow);
3462 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3464 PCFL(pflow)->end = pb->pcTail;
3467 /*-------------------------------------------------------------------*/
3468 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3469 /* the flow blocks. */
3471 * unBuildFlow removes pCodeFlow objects from a pCode chain
3473 /*-----------------------------------------------------------------*/
3474 void unBuildFlow(pBlock *pb)
3489 if(PCI(pc)->pcflow) {
3490 //free(PCI(pc)->pcflow);
3491 PCI(pc)->pcflow = NULL;
3494 } else if(isPCFL(pc) )
3503 /*-----------------------------------------------------------------*/
3504 /*-----------------------------------------------------------------*/
3505 void dumpCond(int cond)
3508 static char *pcc_str[] = {
3522 int ncond = sizeof(pcc_str) / sizeof(char *);
3525 fprintf(stderr, "0x%04X\n",cond);
3527 for(i=0,j=1; i<ncond; i++, j<<=1)
3529 fprintf(stderr, " %s\n",pcc_str[i]);
3533 /*-----------------------------------------------------------------*/
3534 /*-----------------------------------------------------------------*/
3535 void FlowStats(pCodeFlow *pcflow)
3543 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3545 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3548 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3553 fprintf(stderr, " FlowStats inCond: ");
3554 dumpCond(pcflow->inCond);
3555 fprintf(stderr, " FlowStats outCond: ");
3556 dumpCond(pcflow->outCond);
3560 /*-----------------------------------------------------------------*
3561 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3562 * if it affects the banking bits.
3564 * return: -1 == Banking bits are unaffected by this pCode.
3566 * return: > 0 == Banking bits are affected.
3568 * If the banking bits are affected, then the returned value describes
3569 * which bits are affected and how they're affected. The lower half
3570 * of the integer maps to the bits that are affected, the upper half
3571 * to whether they're set or cleared.
3573 *-----------------------------------------------------------------*/
3574 #define SET_BANK_BIT (1 << 16)
3575 #define CLR_BANK_BIT 0
3577 int isBankInstruction(pCode *pc)
3585 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3587 /* Check to see if the register banks are changing */
3588 if(PCI(pc)->isModReg) {
3590 pCodeOp *pcop = PCI(pc)->pcop;
3591 switch(PCI(pc)->op) {
3594 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3595 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3596 return SET_BANK_BIT | PIC_RP0_BIT;
3599 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3600 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3601 return CLR_BANK_BIT | PIC_RP0_BIT;
3606 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3607 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3608 return CLR_BANK_BIT | PIC_RP1_BIT;
3610 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3611 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3612 return CLR_BANK_BIT | PIC_RP1_BIT;
3616 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3617 //genericPrint(stderr, pc);
3628 /*-----------------------------------------------------------------*/
3629 /*-----------------------------------------------------------------*/
3630 void FillFlow(pCodeFlow *pcflow)
3639 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3641 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3644 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3651 isBankInstruction(pc);
3653 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3657 fprintf(stderr, " FillFlow - Bad end of flow\n");
3659 fprintf(stderr, " FillFlow - Ending flow with\n ");
3660 pc->print(stderr,pc);
3663 fprintf(stderr, " FillFlow inCond: ");
3664 dumpCond(pcflow->inCond);
3665 fprintf(stderr, " FillFlow outCond: ");
3666 dumpCond(pcflow->outCond);
3670 /*-----------------------------------------------------------------*/
3671 /*-----------------------------------------------------------------*/
3672 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3674 pCodeFlowLink *fromLink, *toLink;
3676 if(!from || !to || !to->pcflow || !from->pcflow)
3679 fromLink = newpCodeFlowLink(from->pcflow);
3680 toLink = newpCodeFlowLink(to->pcflow);
3682 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3683 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3687 /*-----------------------------------------------------------------*
3688 * void LinkFlow(pBlock *pb)
3690 * In BuildFlow, the PIC code has been partitioned into contiguous
3691 * non-branching segments. In LinkFlow, we determine the execution
3692 * order of these segments. For example, if one of the segments ends
3693 * with a skip, then we know that there are two possible flow segments
3694 * to which control may be passed.
3695 *-----------------------------------------------------------------*/
3696 void LinkFlow(pBlock *pb)
3702 //fprintf(stderr,"linkflow \n");
3704 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3706 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3709 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3711 //fprintf(stderr," link: ");
3712 //pcflow->print(stderr,pcflow);
3714 //FillFlow(PCFL(pcflow));
3716 pc = PCFL(pcflow)->end;
3718 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3719 if(isPCI_SKIP(pc)) {
3720 //fprintf(stderr, "ends with skip\n");
3721 //pc->print(stderr,pc);
3722 pct=findNextInstruction(pc->next);
3723 LinkFlow_pCode(PCI(pc),PCI(pct));
3724 pct=findNextInstruction(pct->next);
3725 LinkFlow_pCode(PCI(pc),PCI(pct));
3729 if(isPCI_BRANCH(pc)) {
3730 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3732 //fprintf(stderr, "ends with branch\n ");
3733 //pc->print(stderr,pc);
3735 if(!(pcol && isPCOLAB(pcol))) {
3736 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3737 pc->print(stderr,pc);
3738 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3743 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3744 LinkFlow_pCode(PCI(pc),PCI(pct));
3746 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3747 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3748 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3754 //fprintf(stderr, "ends with non-branching instruction:\n");
3755 //pc->print(stderr,pc);
3757 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3763 //fprintf(stderr, "ends with unknown\n");
3764 //pc->print(stderr,pc);
3768 //fprintf(stderr, "ends with nothing: ERROR\n");
3772 /*-----------------------------------------------------------------*/
3773 /*-----------------------------------------------------------------*/
3775 /*-----------------------------------------------------------------*/
3776 /*-----------------------------------------------------------------*/
3777 int isPCinFlow(pCode *pc, pCode *pcflow)
3783 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3786 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3792 /*-----------------------------------------------------------------*/
3793 /*-----------------------------------------------------------------*/
3794 void BanksUsedFlow2(pCode *pcflow)
3803 if(!isPCFL(pcflow)) {
3804 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3808 pc = findNextInstruction(pcflow->next);
3810 PCFL(pcflow)->lastBank = -1;
3812 while(isPCinFlow(pc,pcflow)) {
3814 int bank_selected = isBankInstruction(pc);
3816 //if(PCI(pc)->pcflow)
3817 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3819 if(bank_selected > 0) {
3820 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3822 /* This instruction is modifying banking bits before accessing registers */
3824 PCFL(pcflow)->firstBank = -1;
3826 if(PCFL(pcflow)->lastBank == -1)
3827 PCFL(pcflow)->lastBank = 0;
3829 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3830 if(bank_selected & SET_BANK_BIT)
3831 PCFL(pcflow)->lastBank |= bank;
3835 reg = getRegFromInstruction(pc);
3837 if(reg && !isREGinBank(reg, bank)) {
3838 int allbanks = REGallBanks(reg);
3840 PCFL(pcflow)->firstBank = allbanks;
3842 PCFL(pcflow)->lastBank = allbanks;
3849 pc = findNextInstruction(pc->next);
3852 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3853 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3858 /*-----------------------------------------------------------------*/
3859 /*-----------------------------------------------------------------*/
3860 void BanksUsedFlow(pBlock *pb)
3865 //pb->pcHead->print(stderr, pb->pcHead);
3867 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3868 //pcflow->print(stderr,pcflow);
3870 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3872 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3874 BanksUsedFlow2(pcflow);
3880 /*-----------------------------------------------------------------*/
3881 /*-----------------------------------------------------------------*/
3882 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3890 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3892 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3893 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3896 /* insert the bank switch after this pc instruction */
3897 pCode *pcnext = findNextInstruction(pc);
3898 pCodeInsertAfter(pc, new_pc);
3903 pCodeInsertAfter(pc->prev, new_pc);
3905 /* Move the label, if there is one */
3907 if(PCI(pc)->label) {
3908 PCI(new_pc)->label = PCI(pc)->label;
3909 PCI(pc)->label = NULL;
3912 /* The new instruction has the same pcflow block */
3913 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3916 /*-----------------------------------------------------------------*/
3917 /*-----------------------------------------------------------------*/
3918 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3929 pc = findNextInstruction(pcfl->pc.next);
3931 while(isPCinFlow(pc,PCODE(pcfl))) {
3933 reg = getRegFromInstruction(pc);
3936 fprintf(stderr, " %s ",reg->name);
3937 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3942 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
3943 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
3946 /* Examine the instruction before this one to make sure it is
3947 * not a skip type instruction */
3948 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3950 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3954 reg_bank = (reg) ? REG_BANK(reg) : 0;
3956 b = cur_bank ^ reg_bank;
3958 //fprintf(stderr, "Cool! can switch banks\n");
3959 cur_bank = reg_bank;
3964 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3967 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3968 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3972 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3973 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3975 insertBankSwitch(0, pc, -1, -1);
3981 //fprintf(stderr, "Bummer can't switch banks\n");
3987 pc = findNextInstruction(pc->next);
3991 if(pcprev && cur_bank) {
3992 /* Brute force - make sure that we point to bank 0 at the
3993 * end of each flow block */
3994 new_pc = newpCode(POC_BCF,
3995 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3996 pCodeInsertAfter(pcprev, new_pc);
4002 /*-----------------------------------------------------------------*/
4003 /*int compareBankFlow - compare the banking requirements between */
4005 /*-----------------------------------------------------------------*/
4006 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4009 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4012 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4015 if(pcflow->firstBank == -1)
4019 if(pcflowLink->pcflow->firstBank == -1) {
4020 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4021 pcflowLink->pcflow->to :
4022 pcflowLink->pcflow->from);
4023 return compareBankFlow(pcflow, pctl, toORfrom);
4027 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4030 pcflowLink->bank_conflict++;
4031 pcflowLink->pcflow->FromConflicts++;
4032 pcflow->ToConflicts++;
4035 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4038 pcflowLink->bank_conflict++;
4039 pcflowLink->pcflow->ToConflicts++;
4040 pcflow->FromConflicts++;
4044 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4045 pcflowLink->pcflow->pc.seq,
4046 pcflowLink->pcflow->FromConflicts,
4047 pcflowLink->pcflow->ToConflicts);
4052 /*-----------------------------------------------------------------*/
4053 /*-----------------------------------------------------------------*/
4054 void FixBankFlow(pBlock *pb)
4058 pCodeFlowLink *pcfl;
4060 pCode *pcflow_max_To=NULL;
4061 pCode *pcflow_max_From=NULL;
4062 int max_ToConflicts=0;
4063 int max_FromConflicts=0;
4065 //fprintf(stderr,"Fix Bank flow \n");
4066 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4070 First loop through all of the flow objects in this pcode block
4071 and fix the ones that have banking conflicts between the
4075 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4077 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4079 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4081 if(!isPCFL(pcflow)) {
4082 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4086 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4087 PCFL(pcflow)->firstBank >= 0 &&
4088 PCFL(pcflow)->lastBank >= 0 ) {
4090 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4091 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4093 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4094 BanksUsedFlow2(pcflow);
4099 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4101 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4103 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4108 if(!isPCFL(pcflow)) {
4109 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4113 PCFL(pcflow)->FromConflicts = 0;
4114 PCFL(pcflow)->ToConflicts = 0;
4119 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4120 pcfl = setFirstItem(PCFL(pcflow)->from);
4123 pc = PCODE(pcfl->pcflow);
4126 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4127 pc->print(stderr,pc);
4130 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4133 pcfl=setNextItem(PCFL(pcflow)->from);
4136 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4137 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4139 FixRegisterBankingInFlow(PCFL(pcflow),0);
4140 BanksUsedFlow2(pcflow);
4142 continue; /* Don't need to check the flow from here - it's already been fixed */
4149 pcfl = setFirstItem(PCFL(pcflow)->to);
4152 pc = PCODE(pcfl->pcflow);
4154 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4155 pc->print(stderr,pc);
4158 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4161 pcfl=setNextItem(PCFL(pcflow)->to);
4164 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4165 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4167 FixRegisterBankingInFlow(PCFL(pcflow),0);
4168 BanksUsedFlow2(pcflow);
4173 Loop through the flow objects again and find the ones with the
4177 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4179 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4181 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4182 pcflow_max_To = pcflow;
4184 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4185 pcflow_max_From = pcflow;
4189 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4190 PCFL(pcflow_max_To)->pc.seq,
4191 PCFL(pcflow_max_To)->ToConflicts);
4194 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4195 PCFL(pcflow_max_From)->pc.seq,
4196 PCFL(pcflow_max_From)->FromConflicts);
4200 /*-----------------------------------------------------------------*/
4201 /*-----------------------------------------------------------------*/
4202 void DumpFlow(pBlock *pb)
4206 pCodeFlowLink *pcfl;
4209 fprintf(stderr,"Dump flow \n");
4210 pb->pcHead->print(stderr, pb->pcHead);
4212 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4213 pcflow->print(stderr,pcflow);
4215 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4217 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4219 if(!isPCFL(pcflow)) {
4220 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4223 fprintf(stderr,"dumping: ");
4224 pcflow->print(stderr,pcflow);
4225 FlowStats(PCFL(pcflow));
4227 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4229 pc = PCODE(pcfl->pcflow);
4231 fprintf(stderr, " from seq %d:\n",pc->seq);
4233 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4234 pc->print(stderr,pc);
4239 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4241 pc = PCODE(pcfl->pcflow);
4243 fprintf(stderr, " to seq %d:\n",pc->seq);
4245 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4246 pc->print(stderr,pc);
4255 /*-----------------------------------------------------------------*/
4256 /*-----------------------------------------------------------------*/
4257 int OptimizepBlock(pBlock *pb)
4262 if(!pb || !peepOptimizing)
4265 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4267 for(pc = pb->pcHead; pc; pc = pc->next)
4268 matches += pCodePeepMatchRule(pc);
4271 pc = findNextInstruction(pb->pcHead);
4279 if(pCodePeepMatchRule(pc)) {
4284 pc = findNextInstruction(pcprev->next);
4286 pc = findNextInstruction(pb->pcHead);
4288 pc = findNextInstruction(pc->next);
4292 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4297 /*-----------------------------------------------------------------*/
4298 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4299 /*-----------------------------------------------------------------*/
4300 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4304 for(pc = pcs; pc; pc = pc->next) {
4306 if((pc->type == PC_OPCODE) &&
4308 (PCI(pc)->pcop->type == PO_LABEL) &&
4309 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4317 /*-----------------------------------------------------------------*/
4318 /*-----------------------------------------------------------------*/
4319 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4326 (PCI(pc)->pcop->type == PO_LABEL)) {
4328 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4330 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4332 free(pcol->pcop.name);
4334 /* If the key is negative, then we (probably) have a label to
4335 * a function and the name is already defined */
4338 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4342 //sprintf(buffer,"_%05d_DS_",pcl->key);
4344 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4346 pcol->pcop.name = Safe_strdup(s);
4347 pcol->key = pcl->key;
4348 //pc->print(stderr,pc);
4355 /*-----------------------------------------------------------------*/
4356 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4357 /* pCode chain if they're not used. */
4358 /*-----------------------------------------------------------------*/
4359 void pBlockRemoveUnusedLabels(pBlock *pb)
4361 pCode *pc; pCodeLabel *pcl;
4366 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4368 pBranch *pbr = PCI(pc)->label;
4369 if(pbr && pbr->next) {
4370 pCode *pcd = pb->pcHead;
4372 //fprintf(stderr, "multiple labels\n");
4373 //pc->print(stderr,pc);
4378 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4379 //fprintf(stderr,"Used by:\n");
4380 //pcd->print(stderr,pcd);
4382 exchangeLabels(PCL(pbr->pc),pcd);
4391 for(pc = pb->pcHead; pc; pc = pc->next) {
4393 if(isPCL(pc)) // pc->type == PC_LABEL)
4395 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4396 pcl = PCL(PCI(pc)->label->pc);
4399 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4401 /* This pCode is a label, so search the pBlock to see if anyone
4404 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4405 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4406 /* Couldn't find an instruction that refers to this label
4407 * So, unlink the pCode label from it's pCode chain
4408 * and destroy the label */
4409 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4411 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4412 if(pc->type == PC_LABEL) {
4414 pCodeLabelDestruct(pc);
4416 unlinkpCodeFromBranch(pc, PCODE(pcl));
4417 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4428 /*-----------------------------------------------------------------*/
4429 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4430 /* chain and put them into pBranches that are */
4431 /* associated with the appropriate pCode */
4433 /*-----------------------------------------------------------------*/
4434 void pBlockMergeLabels(pBlock *pb)
4437 pCode *pc, *pcnext=NULL;
4442 /* First, Try to remove any unused labels */
4443 //pBlockRemoveUnusedLabels(pb);
4445 /* Now loop through the pBlock and merge the labels with the opcodes */
4448 // for(pc = pb->pcHead; pc; pc = pc->next) {
4451 pCode *pcn = pc->next;
4453 if(pc->type == PC_LABEL) {
4455 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4456 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4457 if((pcnext = findNextInstruction(pc) )) {
4459 // Unlink the pCode label from it's pCode chain
4462 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4463 // And link it into the instruction's pBranch labels. (Note, since
4464 // it's possible to have multiple labels associated with one instruction
4465 // we must provide a means to accomodate the additional labels. Thus
4466 // the labels are placed into the singly-linked list "label" as
4467 // opposed to being a single member of the pCodeInstruction.)
4469 //_ALLOC(pbr,sizeof(pBranch));
4470 pbr = Safe_calloc(1,sizeof(pBranch));
4474 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4477 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4479 } else if(pc->type == PC_CSOURCE) {
4481 /* merge the source line symbolic info into the next instruction */
4482 if((pcnext = findNextInstruction(pc) )) {
4484 // Unlink the pCode label from it's pCode chain
4486 PCI(pcnext)->cline = PCCS(pc);
4487 //fprintf(stderr, "merging CSRC\n");
4488 //genericPrint(stderr,pcnext);
4494 pBlockRemoveUnusedLabels(pb);
4498 /*-----------------------------------------------------------------*/
4499 /*-----------------------------------------------------------------*/
4500 int OptimizepCode(char dbName)
4502 #define MAX_PASSES 4
4511 DFPRINTF((stderr," Optimizing pCode\n"));
4515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4516 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4517 matches += OptimizepBlock(pb);
4520 while(matches && ++passes < MAX_PASSES);
4525 /*-----------------------------------------------------------------*/
4526 /* popCopyGPR2Bit - copy a pcode operator */
4527 /*-----------------------------------------------------------------*/
4529 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4533 pcop = newpCodeOpBit(pc->name, bitval, 0);
4535 if( !( (pcop->type == PO_LABEL) ||
4536 (pcop->type == PO_LITERAL) ||
4537 (pcop->type == PO_STR) ))
4538 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4546 /*-----------------------------------------------------------------*/
4547 /*-----------------------------------------------------------------*/
4548 int InstructionRegBank(pCode *pc)
4552 if( (reg = getRegFromInstruction(pc)) == NULL)
4555 return REG_BANK(reg);
4560 /*-----------------------------------------------------------------*/
4561 /*-----------------------------------------------------------------*/
4562 void FixRegisterBanking(pBlock *pb)
4573 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4574 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4577 /* loop through all of the flow blocks with in one pblock */
4579 //fprintf(stderr,"Register banking\n");
4582 /* at this point, pc should point to a PC_FLOW object */
4585 /* for each flow block, determine the register banking
4590 //genericPrint(stderr, pc);
4592 reg = getRegFromInstruction(pc);
4595 fprintf(stderr, " %s ",reg->name);
4596 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4597 reg->address,REG_BANK(reg),reg->isBitField);
4602 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4603 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4607 /* Examine the instruction before this one to make sure it is
4608 * not a skip type instruction */
4609 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4611 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4615 reg_bank = (reg) ? REG_BANK(reg) : 0;
4617 b = cur_bank ^ reg_bank;
4619 cur_bank = reg_bank;
4624 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4627 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4628 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4632 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4633 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4635 insertBankSwitch(0, pc, -1, -1);
4641 //fprintf(stderr, "Bummer can't switch banks\n");
4651 // } while(pc && !(isPCFL(pc)));
4656 if(pcprev && cur_bank) {
4658 int pos = 1; /* Assume that the bank swithc instruction(s)
4659 * are inserted after this instruction */
4661 if((PCI(pcprev)->op == POC_RETLW) ||
4662 (PCI(pcprev)->op == POC_RETURN) ||
4663 (PCI(pcprev)->op == POC_RETFIE)) {
4665 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4671 /* Brute force - make sure that we point to bank 0 at the
4672 * end of each flow block */
4674 switch(cur_bank & 3) {
4678 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4681 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4682 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4685 insertBankSwitch(pos, pcprev, -1, -1);
4690 new_pc = newpCode(POC_BCF,
4691 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4692 pCodeInsertAfter(pcprev, new_pc);
4695 //fprintf(stderr, "Brute force switch\n");
4704 if(reg && REG_BANK(reg)!=cur_bank) {
4705 //fprintf(stderr,"need to switch banks\n");
4706 /* Examine the instruction before this one to make sure it is
4707 * not a skip type instruction */
4708 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4709 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4710 int b = cur_bank ^ REG_BANK(reg);
4712 cur_bank = REG_BANK(reg);
4718 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4721 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4722 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4726 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4727 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4729 insertBankSwitch(0, pc, -1, -1);
4738 void pBlockDestruct(pBlock *pb)
4749 /*-----------------------------------------------------------------*/
4750 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4751 /* name dbName and combine them */
4752 /* into one block */
4753 /*-----------------------------------------------------------------*/
4754 void mergepBlocks(char dbName)
4757 pBlock *pb, *pbmerged = NULL,*pbn;
4759 pb = the_pFile->pbHead;
4761 //fprintf(stderr," merging blocks named %c\n",dbName);
4765 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4766 if( getpBlock_dbName(pb) == dbName) {
4768 //fprintf(stderr," merged block %c\n",dbName);
4773 addpCode2pBlock(pbmerged, pb->pcHead);
4774 /* addpCode2pBlock doesn't handle the tail: */
4775 pbmerged->pcTail = pb->pcTail;
4777 pb->prev->next = pbn;
4779 pbn->prev = pb->prev;
4784 //printpBlock(stderr, pbmerged);
4791 /*-----------------------------------------------------------------*/
4792 /* AnalyzeFlow - Examine the flow of the code and optimize */
4794 /* level 0 == minimal optimization */
4795 /* optimize registers that are used only by two instructions */
4796 /* level 1 == maximal optimization */
4797 /* optimize by looking at pairs of instructions that use the */
4799 /*-----------------------------------------------------------------*/
4801 void AnalyzeFlow(int level)
4803 static int times_called=0;
4811 /* if this is not the first time this function has been called,
4812 then clean up old flow information */
4813 if(times_called++) {
4814 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4817 RegsUnMapLiveRanges();
4823 /* Phase 2 - Flow Analysis - Register Banking
4825 * In this phase, the individual flow blocks are examined
4826 * and register banking is fixed.
4829 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4830 //FixRegisterBanking(pb);
4832 /* Phase 2 - Flow Analysis
4834 * In this phase, the pCode is partition into pCodeFlow
4835 * blocks. The flow blocks mark the points where a continuous
4836 * stream of instructions changes flow (e.g. because of
4837 * a call or goto or whatever).
4840 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4844 /* Phase 2 - Flow Analysis - linking flow blocks
4846 * In this phase, the individual flow blocks are examined
4847 * to determine their order of excution.
4850 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4853 /* Phase 3 - Flow Analysis - Flow Tree
4855 * In this phase, the individual flow blocks are examined
4856 * to determine their order of excution.
4859 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4863 /* Phase x - Flow Analysis - Used Banks
4865 * In this phase, the individual flow blocks are examined
4866 * to determine the Register Banks they use
4869 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4873 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4874 pCodeRegMapLiveRanges(pb);
4876 RemoveUnusedRegisters();
4878 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4879 pCodeRegOptimizeRegUsage(level);
4885 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4889 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4891 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4892 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4893 pcflow = pcflow->next) {
4895 FillFlow(PCFL(pcflow));
4900 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4902 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4903 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4904 pcflow = pcflow->next) {
4906 FlowStats(PCFL(pcflow));
4912 /*-----------------------------------------------------------------*/
4913 /* AnalyzeBanking - Called after the memory addresses have been */
4914 /* assigned to the registers. */
4916 /*-----------------------------------------------------------------*/
4918 void AnalyzeBanking(void)
4922 if(!picIsInitialized()) {
4923 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4924 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4925 fprintf(stderr,"support/scripts/inc2h.pl\n");
4926 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4931 /* Phase x - Flow Analysis - Used Banks
4933 * In this phase, the individual flow blocks are examined
4934 * to determine the Register Banks they use
4940 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4942 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4943 FixRegisterBanking(pb);
4947 /*-----------------------------------------------------------------*/
4948 /* buildCallTree - look at the flow and extract all of the calls */
4950 /*-----------------------------------------------------------------*/
4951 set *register_usage(pBlock *pb);
4953 void buildCallTree(void )
4964 /* Now build the call tree.
4965 First we examine all of the pCodes for functions.
4966 Keep in mind that the function boundaries coincide
4967 with pBlock boundaries.
4969 The algorithm goes something like this:
4970 We have two nested loops. The outer loop iterates
4971 through all of the pBlocks/functions. The inner
4972 loop iterates through all of the pCodes for
4973 a given pBlock. When we begin iterating through
4974 a pBlock, the variable pc_fstart, pCode of the start
4975 of a function, is cleared. We then search for pCodes
4976 of type PC_FUNCTION. When one is encountered, we
4977 initialize pc_fstart to this and at the same time
4978 associate a new pBranch object that signifies a
4979 branch entry. If a return is found, then this signifies
4980 a function exit point. We'll link the pCodes of these
4981 returns to the matching pc_fstart.
4983 When we're done, a doubly linked list of pBranches
4984 will exist. The head of this list is stored in
4985 `the_pFile', which is the meta structure for all
4986 of the pCode. Look at the printCallTree function
4987 on how the pBranches are linked together.
4990 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4991 pCode *pc_fstart=NULL;
4992 for(pc = pb->pcHead; pc; pc = pc->next) {
4994 if (PCF(pc)->fname) {
4996 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4997 //fprintf(stderr," found main \n");
4998 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5002 pbr = Safe_calloc(1,sizeof(pBranch));
5003 pbr->pc = pc_fstart = pc;
5006 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5008 // Here's a better way of doing the same:
5009 addSet(&pb->function_entries, pc);
5012 // Found an exit point in a function, e.g. return
5013 // (Note, there may be more than one return per function)
5015 pBranchLink(PCF(pc_fstart), PCF(pc));
5017 addSet(&pb->function_exits, pc);
5019 } else if(isCALL(pc)) {
5020 addSet(&pb->function_calls,pc);
5025 /* Re-allocate the registers so that there are no collisions
5026 * between local variables when one function call another */
5029 // pic14_deallocateAllRegs();
5031 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5038 /*-----------------------------------------------------------------*/
5039 /* AnalyzepCode - parse the pCode that has been generated and form */
5040 /* all of the logical connections. */
5042 /* Essentially what's done here is that the pCode flow is */
5044 /*-----------------------------------------------------------------*/
5046 void AnalyzepCode(char dbName)
5057 /* Phase 1 - Register allocation and peep hole optimization
5059 * The first part of the analysis is to determine the registers
5060 * that are used in the pCode. Once that is done, the peep rules
5061 * are applied to the code. We continue to loop until no more
5062 * peep rule optimizations are found (or until we exceed the
5063 * MAX_PASSES threshold).
5065 * When done, the required registers will be determined.
5071 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5072 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5074 /* First, merge the labels with the instructions */
5075 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5076 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5078 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5079 //fprintf(stderr," analyze and merging block %c\n",dbName);
5080 pBlockMergeLabels(pb);
5083 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5087 changes = OptimizepCode(dbName);
5089 } while(changes && (i++ < MAX_PASSES));
5094 /*-----------------------------------------------------------------*/
5095 /* ispCodeFunction - returns true if *pc is the pCode of a */
5097 /*-----------------------------------------------------------------*/
5098 bool ispCodeFunction(pCode *pc)
5101 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5107 /*-----------------------------------------------------------------*/
5108 /* findFunction - Search for a function by name (given the name) */
5109 /* in the set of all functions that are in a pBlock */
5110 /* (note - I expect this to change because I'm planning to limit */
5111 /* pBlock's to just one function declaration */
5112 /*-----------------------------------------------------------------*/
5113 pCode *findFunction(char *fname)
5120 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5122 pc = setFirstItem(pb->function_entries);
5125 if((pc->type == PC_FUNCTION) &&
5127 (strcmp(fname, PCF(pc)->fname)==0))
5130 pc = setNextItem(pb->function_entries);
5138 void MarkUsedRegisters(set *regset)
5143 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5144 r2 = pic14_regWithIdx(r1->rIdx);
5150 void pBlockStats(FILE *of, pBlock *pb)
5156 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5158 // for now just print the first element of each set
5159 pc = setFirstItem(pb->function_entries);
5161 fprintf(of,";entry: ");
5164 pc = setFirstItem(pb->function_exits);
5166 fprintf(of,";has an exit\n");
5170 pc = setFirstItem(pb->function_calls);
5172 fprintf(of,";functions called:\n");
5175 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5176 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5178 pc = setNextItem(pb->function_calls);
5182 r = setFirstItem(pb->tregisters);
5184 int n = elementsInSet(pb->tregisters);
5186 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5189 fprintf(of,"; %s\n",r->name);
5190 r = setNextItem(pb->tregisters);
5195 /*-----------------------------------------------------------------*/
5196 /*-----------------------------------------------------------------*/
5198 static void sequencepCode(void)
5204 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5206 pb->seq = GpCodeSequenceNumber+1;
5208 for( pc = pb->pcHead; pc; pc = pc->next)
5209 pc->seq = ++GpCodeSequenceNumber;
5215 /*-----------------------------------------------------------------*/
5216 /*-----------------------------------------------------------------*/
5217 set *register_usage(pBlock *pb)
5220 set *registers=NULL;
5221 set *registersInCallPath = NULL;
5223 /* check recursion */
5225 pc = setFirstItem(pb->function_entries);
5232 if(pc->type != PC_FUNCTION)
5233 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5235 pc = setFirstItem(pb->function_calls);
5236 for( ; pc; pc = setNextItem(pb->function_calls)) {
5238 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5239 char *dest = get_op_from_instruction(PCI(pc));
5241 pcn = findFunction(dest);
5243 registersInCallPath = register_usage(pcn->pb);
5245 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5250 pBlockStats(stderr,pb); // debug
5253 // Mark the registers in this block as used.
5255 MarkUsedRegisters(pb->tregisters);
5256 if(registersInCallPath) {
5257 /* registers were used in the functions this pBlock has called */
5258 /* so now, we need to see if these collide with the ones we are */
5261 regs *r1,*r2, *newreg;
5263 DFPRINTF((stderr,"comparing registers\n"));
5265 r1 = setFirstItem(registersInCallPath);
5268 r2 = setFirstItem(pb->tregisters);
5270 while(r2 && (r1->type != REG_STK)) {
5272 if(r2->rIdx == r1->rIdx) {
5273 newreg = pic14_findFreeReg(REG_GPR);
5277 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5281 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5282 r1->rIdx, newreg->rIdx));
5283 r2->rIdx = newreg->rIdx;
5284 //if(r2->name) free(r2->name);
5286 r2->name = Safe_strdup(newreg->name);
5290 newreg->wasUsed = 1;
5292 r2 = setNextItem(pb->tregisters);
5295 r1 = setNextItem(registersInCallPath);
5298 /* Collisions have been resolved. Now free the registers in the call path */
5299 r1 = setFirstItem(registersInCallPath);
5301 if(r1->type != REG_STK) {
5302 newreg = pic14_regWithIdx(r1->rIdx);
5305 r1 = setNextItem(registersInCallPath);
5309 // MarkUsedRegisters(pb->registers);
5311 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5314 DFPRINTF((stderr,"returning regs\n"));
5316 DFPRINTF((stderr,"not returning regs\n"));
5318 DFPRINTF((stderr,"pBlock after register optim.\n"));
5319 pBlockStats(stderr,pb); // debug
5325 /*-----------------------------------------------------------------*/
5326 /* printCallTree - writes the call tree to a file */
5328 /*-----------------------------------------------------------------*/
5329 void pct2(FILE *of,pBlock *pb,int indent)
5333 // set *registersInCallPath = NULL;
5339 return; //recursion ?
5341 pc = setFirstItem(pb->function_entries);
5348 for(i=0;i<indent;i++) // Indentation
5351 if(pc->type == PC_FUNCTION)
5352 fprintf(of,"%s\n",PCF(pc)->fname);
5357 pc = setFirstItem(pb->function_calls);
5358 for( ; pc; pc = setNextItem(pb->function_calls)) {
5360 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5361 char *dest = get_op_from_instruction(PCI(pc));
5363 pcn = findFunction(dest);
5365 pct2(of,pcn->pb,indent+1);
5367 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5375 /*-----------------------------------------------------------------*/
5376 /* printCallTree - writes the call tree to a file */
5378 /*-----------------------------------------------------------------*/
5380 void printCallTree(FILE *of)
5392 fprintf(of, "\npBlock statistics\n");
5393 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5398 fprintf(of,"Call Tree\n");
5399 pbr = the_pFile->functions;
5403 if(!ispCodeFunction(pc))
5404 fprintf(of,"bug in call tree");
5407 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5409 while(pc->next && !ispCodeFunction(pc->next)) {
5411 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5412 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5420 fprintf(of,"\n**************\n\na better call tree\n");
5421 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5426 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5427 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5433 /*-----------------------------------------------------------------*/
5435 /*-----------------------------------------------------------------*/
5437 void InlineFunction(pBlock *pb)
5445 pc = setFirstItem(pb->function_calls);
5447 for( ; pc; pc = setNextItem(pb->function_calls)) {
5450 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5456 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5458 //fprintf(stderr,"Cool can inline:\n");
5459 //pcn->print(stderr,pcn);
5461 //fprintf(stderr,"recursive call Inline\n");
5462 InlineFunction(pcn->pb);
5463 //fprintf(stderr,"return from recursive call Inline\n");
5466 At this point, *pc points to a CALL mnemonic, and
5467 *pcn points to the function that is being called.
5469 To in-line this call, we need to remove the CALL
5470 and RETURN(s), and link the function pCode in with
5476 /* Remove the CALL */
5480 /* remove callee pBlock from the pBlock linked list */
5481 removepBlock(pcn->pb);
5489 /* Remove the Function pCode */
5490 pct = findNextInstruction(pcn->next);
5492 /* Link the function with the callee */
5493 pc->next = pcn->next;
5494 pcn->next->prev = pc;
5496 /* Convert the function name into a label */
5498 pbr = Safe_calloc(1,sizeof(pBranch));
5499 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5501 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5502 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5504 /* turn all of the return's except the last into goto's */
5505 /* check case for 2 instruction pBlocks */
5506 pce = findNextInstruction(pcn->next);
5508 pCode *pce_next = findNextInstruction(pce->next);
5510 if(pce_next == NULL) {
5511 /* found the last return */
5512 pCode *pc_call_next = findNextInstruction(pc_call->next);
5514 //fprintf(stderr,"found last return\n");
5515 //pce->print(stderr,pce);
5516 pce->prev->next = pc_call->next;
5517 pc_call->next->prev = pce->prev;
5518 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5528 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5534 /*-----------------------------------------------------------------*/
5536 /*-----------------------------------------------------------------*/
5538 void InlinepCode(void)
5547 if(!functionInlining)
5550 /* Loop through all of the function definitions and count the
5551 * number of times each one is called */
5552 //fprintf(stderr,"inlining %d\n",__LINE__);
5554 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5556 pc = setFirstItem(pb->function_calls);
5558 for( ; pc; pc = setNextItem(pb->function_calls)) {
5561 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5562 if(pcn && isPCF(pcn)) {
5563 PCF(pcn)->ncalled++;
5566 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5571 //fprintf(stderr,"inlining %d\n",__LINE__);
5573 /* Now, Loop through the function definitions again, but this
5574 * time inline those functions that have only been called once. */
5576 InlineFunction(the_pFile->pbHead);
5577 //fprintf(stderr,"inlining %d\n",__LINE__);
5579 for(pb = the_pFile->pbHead; pb; pb = pb->next)