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