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,size_t buf_size);
109 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
110 int pCodePeepMatchRule(pCode *pc);
111 void pBlockStats(FILE *of, pBlock *pb);
112 pBlock *newpBlock(void);
113 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
114 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
115 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
116 void pCodeRegMapLiveRanges(pBlock *pb);
119 /****************************************************************/
120 /* PIC Instructions */
121 /****************************************************************/
123 pCodeInstruction pciADDWF = {
124 {PC_OPCODE, NULL, NULL, 0, NULL,
137 1,0, // dest, bit instruction
139 0, // literal operand
141 (PCC_W | PCC_REGISTER), // inCond
142 (PCC_REGISTER | PCC_Z) // outCond
145 pCodeInstruction pciADDFW = {
146 {PC_OPCODE, NULL, NULL, 0, NULL,
159 0,0, // dest, bit instruction
161 0, // literal operand
163 (PCC_W | PCC_REGISTER), // inCond
164 (PCC_W | PCC_Z) // outCond
167 pCodeInstruction pciADDLW = {
168 {PC_OPCODE, NULL, NULL, 0, NULL,
181 0,0, // dest, bit instruction
183 1, // literal operand
185 (PCC_W | PCC_LITERAL), // inCond
186 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
189 pCodeInstruction pciANDLW = {
190 {PC_OPCODE, NULL, NULL, 0, NULL,
203 0,0, // dest, bit instruction
205 1, // literal operand
207 (PCC_W | PCC_LITERAL), // inCond
208 (PCC_W | PCC_Z) // outCond
211 pCodeInstruction pciANDWF = {
212 {PC_OPCODE, NULL, NULL, 0, NULL,
225 1,0, // dest, bit instruction
227 0, // literal operand
229 (PCC_W | PCC_REGISTER), // inCond
230 (PCC_REGISTER | PCC_Z) // outCond
233 pCodeInstruction pciANDFW = {
234 {PC_OPCODE, NULL, NULL, 0, NULL,
247 0,0, // dest, bit instruction
249 0, // literal operand
251 (PCC_W | PCC_REGISTER), // inCond
252 (PCC_W | PCC_Z) // outCond
255 pCodeInstruction pciBCF = {
256 {PC_OPCODE, NULL, NULL, 0, NULL,
269 1,1, // dest, bit instruction
271 0, // literal operand
273 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
274 PCC_REGISTER // outCond
277 pCodeInstruction pciBSF = {
278 {PC_OPCODE, NULL, NULL, 0, NULL,
291 1,1, // dest, bit instruction
293 0, // literal operand
295 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
296 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
299 pCodeInstruction pciBTFSC = {
300 {PC_OPCODE, NULL, NULL, 0, NULL,
313 0,1, // dest, bit instruction
315 0, // literal operand
317 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
318 PCC_EXAMINE_PCOP // outCond
321 pCodeInstruction pciBTFSS = {
322 {PC_OPCODE, NULL, NULL, 0, NULL,
335 0,1, // dest, bit instruction
337 0, // literal operand
339 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
340 PCC_EXAMINE_PCOP // outCond
343 pCodeInstruction pciCALL = {
344 {PC_OPCODE, NULL, NULL, 0, NULL,
357 0,0, // dest, bit instruction
359 0, // literal operand
365 pCodeInstruction pciCOMF = {
366 {PC_OPCODE, NULL, NULL, 0, NULL,
379 1,0, // dest, bit instruction
381 0, // literal operand
383 PCC_REGISTER, // inCond
384 PCC_REGISTER // outCond
387 pCodeInstruction pciCOMFW = {
388 {PC_OPCODE, NULL, NULL, 0, NULL,
401 0,0, // dest, bit instruction
403 0, // literal operand
405 PCC_REGISTER, // inCond
409 pCodeInstruction pciCLRF = {
410 {PC_OPCODE, NULL, NULL, 0, NULL,
423 0,0, // dest, bit instruction
425 0, // literal operand
428 PCC_REGISTER // outCond
431 pCodeInstruction pciCLRW = {
432 {PC_OPCODE, NULL, NULL, 0, NULL,
445 0,0, // dest, bit instruction
447 0, // literal operand
453 pCodeInstruction pciCLRWDT = {
454 {PC_OPCODE, NULL, NULL, 0, NULL,
467 0,0, // dest, bit instruction
469 0, // literal operand
475 pCodeInstruction pciDECF = {
476 {PC_OPCODE, NULL, NULL, 0, NULL,
489 1,0, // dest, bit instruction
491 0, // literal operand
493 PCC_REGISTER, // inCond
494 PCC_REGISTER // outCond
497 pCodeInstruction pciDECFW = {
498 {PC_OPCODE, NULL, NULL, 0, NULL,
511 0,0, // dest, bit instruction
513 0, // literal operand
515 PCC_REGISTER, // inCond
519 pCodeInstruction pciDECFSZ = {
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 1,0, // dest, bit instruction
535 0, // literal operand
537 PCC_REGISTER, // inCond
538 PCC_REGISTER // outCond
541 pCodeInstruction pciDECFSZW = {
542 {PC_OPCODE, NULL, NULL, 0, NULL,
555 0,0, // dest, bit instruction
557 0, // literal operand
559 PCC_REGISTER, // inCond
563 pCodeInstruction pciGOTO = {
564 {PC_OPCODE, NULL, NULL, 0, NULL,
577 0,0, // dest, bit instruction
579 0, // literal operand
585 pCodeInstruction pciINCF = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 1,0, // dest, bit instruction
601 0, // literal operand
603 PCC_REGISTER, // inCond
604 PCC_REGISTER // outCond
607 pCodeInstruction pciINCFW = {
608 {PC_OPCODE, NULL, NULL, 0, NULL,
621 0,0, // dest, bit instruction
623 0, // literal operand
625 PCC_REGISTER, // inCond
629 pCodeInstruction pciINCFSZ = {
630 {PC_OPCODE, NULL, NULL, 0, NULL,
643 1,0, // dest, bit instruction
645 0, // literal operand
647 PCC_REGISTER, // inCond
648 PCC_REGISTER // outCond
651 pCodeInstruction pciINCFSZW = {
652 {PC_OPCODE, NULL, NULL, 0, NULL,
665 0,0, // dest, bit instruction
667 0, // literal operand
669 PCC_REGISTER, // inCond
673 pCodeInstruction pciIORWF = {
674 {PC_OPCODE, NULL, NULL, 0, NULL,
687 1,0, // dest, bit instruction
689 0, // literal operand
691 (PCC_W | PCC_REGISTER), // inCond
692 (PCC_REGISTER | PCC_Z) // outCond
695 pCodeInstruction pciIORFW = {
696 {PC_OPCODE, NULL, NULL, 0, NULL,
709 0,0, // dest, bit instruction
711 0, // literal operand
713 (PCC_W | PCC_REGISTER), // inCond
714 (PCC_W | PCC_Z) // outCond
717 pCodeInstruction pciIORLW = {
718 {PC_OPCODE, NULL, NULL, 0, NULL,
731 0,0, // dest, bit instruction
733 1, // literal operand
735 (PCC_W | PCC_LITERAL), // inCond
736 (PCC_W | PCC_Z) // outCond
739 pCodeInstruction pciMOVF = {
740 {PC_OPCODE, NULL, NULL, 0, NULL,
753 1,0, // dest, bit instruction
755 0, // literal operand
757 PCC_REGISTER, // inCond
761 pCodeInstruction pciMOVFW = {
762 {PC_OPCODE, NULL, NULL, 0, NULL,
775 0,0, // dest, bit instruction
777 0, // literal operand
779 PCC_REGISTER, // inCond
780 (PCC_W | PCC_Z) // outCond
783 pCodeInstruction pciMOVWF = {
784 {PC_OPCODE, NULL, NULL, 0, NULL,
797 0,0, // dest, bit instruction
799 0, // literal operand
802 PCC_REGISTER // outCond
805 pCodeInstruction pciMOVLW = {
806 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 1, // literal operand
822 (PCC_NONE | PCC_LITERAL), // inCond
826 pCodeInstruction pciNOP = {
827 {PC_OPCODE, NULL, NULL, 0, NULL,
839 0,0, // dest, bit instruction
841 0, // literal operand
847 pCodeInstruction pciRETFIE = {
848 {PC_OPCODE, NULL, NULL, 0, NULL,
861 0,0, // dest, bit instruction
863 0, // literal operand
866 PCC_NONE // outCond (not true... affects the GIE bit too)
869 pCodeInstruction pciRETLW = {
870 {PC_OPCODE, NULL, NULL, 0, NULL,
883 0,0, // dest, bit instruction
885 1, // literal operand
887 PCC_LITERAL, // inCond
891 pCodeInstruction pciRETURN = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
905 0,0, // dest, bit instruction
907 0, // literal operand
913 pCodeInstruction pciRLF = {
914 {PC_OPCODE, NULL, NULL, 0, NULL,
927 1,0, // dest, bit instruction
929 0, // literal operand
931 (PCC_C | PCC_REGISTER), // inCond
932 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
935 pCodeInstruction pciRLFW = {
936 {PC_OPCODE, NULL, NULL, 0, NULL,
949 0,0, // dest, bit instruction
951 0, // literal operand
953 (PCC_C | PCC_REGISTER), // inCond
954 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
957 pCodeInstruction pciRRF = {
958 {PC_OPCODE, NULL, NULL, 0, NULL,
971 1,0, // dest, bit instruction
973 0, // literal operand
975 (PCC_C | PCC_REGISTER), // inCond
976 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
979 pCodeInstruction pciRRFW = {
980 {PC_OPCODE, NULL, NULL, 0, NULL,
993 0,0, // dest, bit instruction
995 0, // literal operand
997 (PCC_C | PCC_REGISTER), // inCond
998 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1001 pCodeInstruction pciSUBWF = {
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1008 NULL, // from branch
1015 1,0, // dest, bit instruction
1016 0,0, // branch, skip
1017 0, // literal operand
1019 (PCC_W | PCC_REGISTER), // inCond
1020 (PCC_REGISTER | PCC_Z) // outCond
1023 pCodeInstruction pciSUBFW = {
1024 {PC_OPCODE, NULL, NULL, 0, NULL,
1030 NULL, // from branch
1037 0,0, // dest, bit instruction
1038 0,0, // branch, skip
1039 0, // literal operand
1041 (PCC_W | PCC_REGISTER), // inCond
1042 (PCC_W | PCC_Z) // outCond
1045 pCodeInstruction pciSUBLW = {
1046 {PC_OPCODE, NULL, NULL, 0, NULL,
1052 NULL, // from branch
1059 0,0, // dest, bit instruction
1060 0,0, // branch, skip
1061 1, // literal operand
1063 (PCC_W | PCC_LITERAL), // inCond
1064 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1067 pCodeInstruction pciSWAPF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1085 (PCC_REGISTER), // inCond
1086 (PCC_REGISTER) // outCond
1089 pCodeInstruction pciSWAPFW = {
1090 {PC_OPCODE, NULL, NULL, 0, NULL,
1096 NULL, // from branch
1103 0,0, // dest, bit instruction
1104 0,0, // branch, skip
1105 0, // literal operand
1107 (PCC_REGISTER), // inCond
1111 pCodeInstruction pciTRIS = {
1112 {PC_OPCODE, NULL, NULL, 0, NULL,
1118 NULL, // from branch
1125 0,0, // dest, bit instruction
1126 0,0, // branch, skip
1127 0, // literal operand
1130 PCC_REGISTER // outCond
1133 pCodeInstruction pciXORWF = {
1134 {PC_OPCODE, NULL, NULL, 0, NULL,
1140 NULL, // from branch
1147 1,0, // dest, bit instruction
1148 0,0, // branch, skip
1149 0, // literal operand
1151 (PCC_W | PCC_REGISTER), // inCond
1152 (PCC_REGISTER | PCC_Z) // outCond
1155 pCodeInstruction pciXORFW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1162 NULL, // from branch
1169 0,0, // dest, bit instruction
1170 0,0, // branch, skip
1171 0, // literal operand
1173 (PCC_W | PCC_REGISTER), // inCond
1174 (PCC_W | PCC_Z) // outCond
1177 pCodeInstruction pciXORLW = {
1178 {PC_OPCODE, NULL, NULL, 0, NULL,
1184 NULL, // from branch
1191 0,0, // dest, bit instruction
1192 0,0, // branch, skip
1193 1, // literal operand
1195 (PCC_W | PCC_LITERAL), // inCond
1196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1200 #define MAX_PIC14MNEMONICS 100
1201 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1204 #ifdef HAVE_VSNPRINTF
1205 // Alas, vsnprintf is not ANSI standard, and does not exist
1206 // on Solaris (and probably other non-Gnu flavored Unixes).
1208 /*-----------------------------------------------------------------*/
1209 /* SAFE_snprintf - like snprintf except the string pointer is */
1210 /* after the string has been printed to. This is */
1211 /* useful for printing to string as though if it */
1212 /* were a stream. */
1213 /*-----------------------------------------------------------------*/
1214 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1222 va_start(val, format);
1224 vsnprintf(*str, *size, format, val);
1230 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1231 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1239 #else // HAVE_VSNPRINTF
1241 // This version is *not* safe, despite the name.
1243 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1247 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1252 va_start(val, format);
1254 vsprintf(buffer, format, val);
1257 len = strlen(buffer);
1259 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1260 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1263 strcpy(*str, buffer);
1269 #endif // HAVE_VSNPRINTF
1272 extern void initStack(int base_address, int size);
1273 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1274 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1275 extern void init_pic(char *);
1277 void pCodeInitRegisters(void)
1279 static int initialized=0;
1285 initStack(0xfff, 8);
1286 init_pic(port->processor);
1288 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1289 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1290 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1291 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1292 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1293 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1295 pc_status.rIdx = IDX_STATUS;
1296 pc_fsr.rIdx = IDX_FSR;
1297 pc_indf.rIdx = IDX_INDF;
1298 pc_intcon.rIdx = IDX_INTCON;
1299 pc_pcl.rIdx = IDX_PCL;
1300 pc_pclath.rIdx = IDX_PCLATH;
1302 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1303 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1304 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1306 pc_kzero.rIdx = IDX_KZ;
1307 pc_wsave.rIdx = IDX_WSAVE;
1308 pc_ssave.rIdx = IDX_SSAVE;
1310 /* probably should put this in a separate initialization routine */
1311 pb_dead_pcodes = newpBlock();
1315 /*-----------------------------------------------------------------*/
1316 /* mnem2key - convert a pic mnemonic into a hash key */
1317 /* (BTW - this spreads the mnemonics quite well) */
1319 /*-----------------------------------------------------------------*/
1321 int mnem2key(char const *mnem)
1330 key += toupper(*mnem++) +1;
1334 return (key & 0x1f);
1338 void pic14initMnemonics(void)
1343 pCodeInstruction *pci;
1345 if(mnemonics_initialized)
1348 //FIXME - probably should NULL out the array before making the assignments
1349 //since we check the array contents below this initialization.
1351 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1352 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1353 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1354 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1355 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1356 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1357 pic14Mnemonics[POC_BCF] = &pciBCF;
1358 pic14Mnemonics[POC_BSF] = &pciBSF;
1359 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1360 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1361 pic14Mnemonics[POC_CALL] = &pciCALL;
1362 pic14Mnemonics[POC_COMF] = &pciCOMF;
1363 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1364 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1365 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1366 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1367 pic14Mnemonics[POC_DECF] = &pciDECF;
1368 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1369 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1370 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1371 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1372 pic14Mnemonics[POC_INCF] = &pciINCF;
1373 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1374 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1375 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1376 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1377 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1378 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1379 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1380 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1381 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1382 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1383 pic14Mnemonics[POC_NOP] = &pciNOP;
1384 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1385 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1386 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1387 pic14Mnemonics[POC_RLF] = &pciRLF;
1388 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1389 pic14Mnemonics[POC_RRF] = &pciRRF;
1390 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1391 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1392 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1393 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1394 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1395 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1396 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1397 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1398 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1399 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1401 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1402 if(pic14Mnemonics[i])
1403 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1404 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1407 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1408 pci = hTabNextItem(pic14MnemonicsHash, &key);
1411 mnemonics_initialized = 1;
1414 int getpCodePeepCommand(char *cmd);
1416 int getpCode(char *mnem,unsigned dest)
1419 pCodeInstruction *pci;
1420 int key = mnem2key(mnem);
1422 if(!mnemonics_initialized)
1423 pic14initMnemonics();
1425 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1429 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1430 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1434 pci = hTabNextItemWK (pic14MnemonicsHash);
1441 /*-----------------------------------------------------------------*
1442 * pic14initpCodePeepCommands
1444 *-----------------------------------------------------------------*/
1445 void pic14initpCodePeepCommands(void)
1453 hTabAddItem(&pic14pCodePeepCommandsHash,
1454 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1456 } while (peepCommands[i].cmd);
1458 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1461 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1462 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1467 /*-----------------------------------------------------------------
1470 *-----------------------------------------------------------------*/
1472 int getpCodePeepCommand(char *cmd)
1476 int key = mnem2key(cmd);
1479 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1482 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1483 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1487 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1494 char getpBlock_dbName(pBlock *pb)
1500 return pb->cmemmap->dbName;
1504 void pBlockConvert2ISR(pBlock *pb)
1515 /*-----------------------------------------------------------------*/
1516 /* movepBlock2Head - given the dbname of a pBlock, move all */
1517 /* instances to the front of the doubly linked */
1518 /* list of pBlocks */
1519 /*-----------------------------------------------------------------*/
1521 void movepBlock2Head(char dbName)
1525 pb = the_pFile->pbHead;
1529 if(getpBlock_dbName(pb) == dbName) {
1530 pBlock *pbn = pb->next;
1531 pb->next = the_pFile->pbHead;
1532 the_pFile->pbHead->prev = pb;
1533 the_pFile->pbHead = pb;
1536 pb->prev->next = pbn;
1538 // If the pBlock that we just moved was the last
1539 // one in the link of all of the pBlocks, then we
1540 // need to point the tail to the block just before
1541 // the one we moved.
1542 // Note: if pb->next is NULL, then pb must have
1543 // been the last pBlock in the chain.
1546 pbn->prev = pb->prev;
1548 the_pFile->pbTail = pb->prev;
1559 void copypCode(FILE *of, char dbName)
1563 if(!of || !the_pFile)
1566 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1567 if(getpBlock_dbName(pb) == dbName) {
1575 void pcode_test(void)
1578 DFPRINTF((stderr,"pcode is alive!\n"));
1588 /* create the file name */
1589 strcpy(buffer,dstFileName);
1590 strcat(buffer,".p");
1592 if( !(pFile = fopen(buffer, "w" ))) {
1593 werror(E_FILE_OPEN_ERR,buffer);
1597 fprintf(pFile,"pcode dump\n\n");
1599 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1600 fprintf(pFile,"\n\tNew pBlock\n\n");
1602 fprintf(pFile,"%s",pb->cmemmap->sname);
1604 fprintf(pFile,"internal pblock");
1606 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1607 printpBlock(pFile,pb);
1611 /*-----------------------------------------------------------------*/
1612 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1613 /* ister, RegCond will return the bit being referenced. */
1615 /* fixme - why not just OR in the pcop bit field */
1616 /*-----------------------------------------------------------------*/
1618 static int RegCond(pCodeOp *pcop)
1624 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1625 switch(PCORB(pcop)->bit) {
1639 /*-----------------------------------------------------------------*/
1640 /* newpCode - create and return a newly initialized pCode */
1642 /* fixme - rename this */
1644 /* The purpose of this routine is to create a new Instruction */
1645 /* pCode. This is called by gen.c while the assembly code is being */
1649 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1650 /* (note that the op is analogous to but not the */
1651 /* same thing as the opcode of the instruction.) */
1652 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1655 /* a pointer to the new malloc'd pCode is returned. */
1659 /*-----------------------------------------------------------------*/
1660 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1662 pCodeInstruction *pci ;
1664 if(!mnemonics_initialized)
1665 pic14initMnemonics();
1667 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1669 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1670 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1673 if(pci->inCond & PCC_EXAMINE_PCOP)
1674 pci->inCond |= RegCond(pcop);
1676 if(pci->outCond & PCC_EXAMINE_PCOP)
1677 pci->outCond |= RegCond(pcop);
1679 pci->pc.prev = pci->pc.next = NULL;
1680 return (pCode *)pci;
1683 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1689 /*-----------------------------------------------------------------*/
1690 /* newpCodeWild - create a "wild" as in wild card pCode */
1692 /* Wild pcodes are used during the peep hole optimizer to serve */
1693 /* as place holders for any instruction. When a snippet of code is */
1694 /* compared to a peep hole rule, the wild card opcode will match */
1695 /* any instruction. However, the optional operand and label are */
1696 /* additional qualifiers that must also be matched before the */
1697 /* line (of assembly code) is declared matched. Note that the */
1698 /* operand may be wild too. */
1700 /* Note, a wild instruction is specified just like a wild var: */
1701 /* %4 ; A wild instruction, */
1702 /* See the peeph.def file for additional examples */
1704 /*-----------------------------------------------------------------*/
1706 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1711 pcw = Safe_calloc(1,sizeof(pCodeWild));
1713 pcw->pci.pc.type = PC_WILD;
1714 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1715 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1716 pcw->pci.pc.pb = NULL;
1718 // pcw->pci.pc.analyze = genericAnalyze;
1719 pcw->pci.pc.destruct = genericDestruct;
1720 pcw->pci.pc.print = genericPrint;
1722 pcw->id = pCodeID; // this is the 'n' in %n
1723 pcw->operand = optional_operand;
1724 pcw->label = optional_label;
1726 pcw->mustBeBitSkipInst = 0;
1727 pcw->mustNotBeBitSkipInst = 0;
1728 pcw->invertBitSkipInst = 0;
1730 return ( (pCode *)pcw);
1734 /*-----------------------------------------------------------------*/
1735 /* newPcodeInlineP - create a new pCode from a char string */
1736 /*-----------------------------------------------------------------*/
1739 pCode *newpCodeInlineP(char *cP)
1744 pcc = Safe_calloc(1,sizeof(pCodeComment));
1746 pcc->pc.type = PC_INLINE;
1747 pcc->pc.prev = pcc->pc.next = NULL;
1748 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1751 // pcc->pc.analyze = genericAnalyze;
1752 pcc->pc.destruct = genericDestruct;
1753 pcc->pc.print = genericPrint;
1756 pcc->comment = Safe_strdup(cP);
1758 pcc->comment = NULL;
1760 return ( (pCode *)pcc);
1764 /*-----------------------------------------------------------------*/
1765 /* newPcodeCharP - create a new pCode from a char string */
1766 /*-----------------------------------------------------------------*/
1768 pCode *newpCodeCharP(char *cP)
1773 pcc = Safe_calloc(1,sizeof(pCodeComment));
1775 pcc->pc.type = PC_COMMENT;
1776 pcc->pc.prev = pcc->pc.next = NULL;
1777 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1780 // pcc->pc.analyze = genericAnalyze;
1781 pcc->pc.destruct = genericDestruct;
1782 pcc->pc.print = genericPrint;
1785 pcc->comment = Safe_strdup(cP);
1787 pcc->comment = NULL;
1789 return ( (pCode *)pcc);
1793 /*-----------------------------------------------------------------*/
1794 /* newpCodeFunction - */
1795 /*-----------------------------------------------------------------*/
1798 pCode *newpCodeFunction(char *mod,char *f)
1802 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1803 //_ALLOC(pcf,sizeof(pCodeFunction));
1805 pcf->pc.type = PC_FUNCTION;
1806 pcf->pc.prev = pcf->pc.next = NULL;
1807 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1810 // pcf->pc.analyze = genericAnalyze;
1811 pcf->pc.destruct = genericDestruct;
1812 pcf->pc.print = pCodePrintFunction;
1817 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1818 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1819 strcpy(pcf->modname,mod);
1821 pcf->modname = NULL;
1824 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1825 pcf->fname = Safe_calloc(1,strlen(f)+1);
1826 strcpy(pcf->fname,f);
1830 return ( (pCode *)pcf);
1834 /*-----------------------------------------------------------------*/
1836 /*-----------------------------------------------------------------*/
1837 void destructpCodeFlow(pCode *pc)
1839 if(!pc || !isPCFL(pc))
1848 deleteSet(&PCFL(pc)->registers);
1849 deleteSet(&PCFL(pc)->from);
1850 deleteSet(&PCFL(pc)->to);
1855 pCode *newpCodeFlow(void )
1859 //_ALLOC(pcflow,sizeof(pCodeFlow));
1860 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1862 pcflow->pc.type = PC_FLOW;
1863 pcflow->pc.prev = pcflow->pc.next = NULL;
1864 pcflow->pc.pb = NULL;
1866 // pcflow->pc.analyze = genericAnalyze;
1867 pcflow->pc.destruct = destructpCodeFlow;
1868 pcflow->pc.print = genericPrint;
1870 pcflow->pc.seq = GpcFlowSeq++;
1872 pcflow->from = pcflow->to = NULL;
1874 pcflow->inCond = PCC_NONE;
1875 pcflow->outCond = PCC_NONE;
1877 pcflow->firstBank = -1;
1878 pcflow->lastBank = -1;
1880 pcflow->FromConflicts = 0;
1881 pcflow->ToConflicts = 0;
1885 pcflow->registers = newSet();
1887 return ( (pCode *)pcflow);
1891 /*-----------------------------------------------------------------*/
1892 /*-----------------------------------------------------------------*/
1893 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1895 pCodeFlowLink *pcflowLink;
1897 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1899 pcflowLink->pcflow = pcflow;
1900 pcflowLink->bank_conflict = 0;
1905 /*-----------------------------------------------------------------*/
1906 /* newpCodeCSource - create a new pCode Source Symbol */
1907 /*-----------------------------------------------------------------*/
1909 pCode *newpCodeCSource(int ln, char *f, char *l)
1914 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1916 pccs->pc.type = PC_CSOURCE;
1917 pccs->pc.prev = pccs->pc.next = NULL;
1920 pccs->pc.destruct = genericDestruct;
1921 pccs->pc.print = genericPrint;
1923 pccs->line_number = ln;
1925 pccs->line = Safe_strdup(l);
1930 pccs->file_name = Safe_strdup(f);
1932 pccs->file_name = NULL;
1934 return ( (pCode *)pccs);
1937 /*-----------------------------------------------------------------*/
1938 /* pCodeLabelDestruct - free memory used by a label. */
1939 /*-----------------------------------------------------------------*/
1940 static void pCodeLabelDestruct(pCode *pc)
1946 if((pc->type == PC_LABEL) && PCL(pc)->label)
1947 free(PCL(pc)->label);
1953 pCode *newpCodeLabel(char *name, int key)
1959 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1961 pcl->pc.type = PC_LABEL;
1962 pcl->pc.prev = pcl->pc.next = NULL;
1963 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1966 // pcl->pc.analyze = genericAnalyze;
1967 pcl->pc.destruct = pCodeLabelDestruct;
1968 pcl->pc.print = pCodePrintLabel;
1974 sprintf(s,"_%05d_DS_",key);
1979 pcl->label = Safe_strdup(s);
1981 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1982 return ( (pCode *)pcl);
1987 /*-----------------------------------------------------------------*/
1988 /* newpBlock - create and return a pointer to a new pBlock */
1989 /*-----------------------------------------------------------------*/
1990 pBlock *newpBlock(void)
1995 PpB = Safe_calloc(1,sizeof(pBlock) );
1996 PpB->next = PpB->prev = NULL;
1998 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1999 PpB->tregisters = NULL;
2001 PpB->FlowTree = NULL;
2007 /*-----------------------------------------------------------------*/
2008 /* newpCodeChain - create a new chain of pCodes */
2009 /*-----------------------------------------------------------------*
2011 * This function will create a new pBlock and the pointer to the
2012 * pCode that is passed in will be the first pCode in the block.
2013 *-----------------------------------------------------------------*/
2016 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2019 pBlock *pB = newpBlock();
2021 pB->pcHead = pB->pcTail = pc;
2028 /*-----------------------------------------------------------------*/
2029 /* newpCodeOpLabel - Create a new label given the key */
2030 /* Note, a negative key means that the label is part of wild card */
2031 /* (and hence a wild card label) used in the pCodePeep */
2032 /* optimizations). */
2033 /*-----------------------------------------------------------------*/
2035 pCodeOp *newpCodeOpLabel(char *name, int key)
2038 static int label_key=-1;
2042 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2043 pcop->type = PO_LABEL;
2048 sprintf(s=buffer,"_%05d_DS_",key);
2050 s = name, key = label_key--;
2053 pcop->name = Safe_strdup(s);
2055 ((pCodeOpLabel *)pcop)->key = key;
2057 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2061 /*-----------------------------------------------------------------*/
2062 /*-----------------------------------------------------------------*/
2063 pCodeOp *newpCodeOpLit(int lit)
2069 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2070 pcop->type = PO_LITERAL;
2074 sprintf(s,"0x%02x",lit);
2076 pcop->name = Safe_strdup(s);
2079 ((pCodeOpLit *)pcop)->lit = lit;
2084 /*-----------------------------------------------------------------*/
2085 /*-----------------------------------------------------------------*/
2086 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2090 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2091 pcop->type = PO_IMMEDIATE;
2094 pcop->name = Safe_strdup(name);
2097 r = dirregWithName(name);
2101 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2102 PCOI(pcop)->rIdx = r->rIdx;
2104 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2105 PCOI(pcop)->rIdx = -1;
2107 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2112 PCOI(pcop)->index = index;
2113 PCOI(pcop)->offset = offset;
2114 PCOI(pcop)->_const = code_space;
2115 PCOI(pcop)->_function = is_func;
2120 /*-----------------------------------------------------------------*/
2121 /*-----------------------------------------------------------------*/
2122 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2128 if(!pcwb || !subtype) {
2129 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2133 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2134 pcop->type = PO_WILD;
2135 sprintf(s,"%%%d",id);
2136 pcop->name = Safe_strdup(s);
2138 PCOW(pcop)->id = id;
2139 PCOW(pcop)->pcwb = pcwb;
2140 PCOW(pcop)->subtype = subtype;
2141 PCOW(pcop)->matched = NULL;
2146 /*-----------------------------------------------------------------*/
2147 /*-----------------------------------------------------------------*/
2148 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2152 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2153 pcop->type = PO_GPR_BIT;
2155 pcop->name = Safe_strdup(s);
2159 PCORB(pcop)->bit = bit;
2160 PCORB(pcop)->inBitSpace = inBitSpace;
2162 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
2163 PCOR(pcop)->r = NULL;
2164 PCOR(pcop)->rIdx = 0;
2168 /*-----------------------------------------------------------------*
2169 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2171 * If rIdx >=0 then a specific register from the set of registers
2172 * will be selected. If rIdx <0, then a new register will be searched
2174 *-----------------------------------------------------------------*/
2176 pCodeOp *newpCodeOpReg(int rIdx)
2180 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2185 PCOR(pcop)->rIdx = rIdx;
2186 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2188 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2191 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2194 pcop->type = PCOR(pcop)->r->pc_type;
2199 pCodeOp *newpCodeOpRegFromStr(char *name)
2203 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2204 PCOR(pcop)->r = allocRegByName(name, 1);
2205 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2206 pcop->type = PCOR(pcop)->r->pc_type;
2207 pcop->name = PCOR(pcop)->r->name;
2212 /*-----------------------------------------------------------------*/
2213 /*-----------------------------------------------------------------*/
2215 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2222 pcop = newpCodeOpBit(name, -1,0);
2226 pcop = newpCodeOpLit(-1);
2230 pcop = newpCodeOpLabel(NULL,-1);
2233 pcop = newpCodeOpReg(-1);
2236 case PO_GPR_POINTER:
2237 case PO_GPR_REGISTER:
2239 pcop = newpCodeOpRegFromStr(name);
2241 pcop = newpCodeOpReg(-1);
2245 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2248 pcop->name = Safe_strdup(name);
2256 /*-----------------------------------------------------------------*/
2257 /*-----------------------------------------------------------------*/
2258 void pCodeConstString(char *name, char *value)
2262 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2267 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2271 sprintf(buffer,"; %s = %s",name,value);
2273 addpCode2pBlock(pb,newpCodeCharP(buffer));
2274 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2277 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2283 /*-----------------------------------------------------------------*/
2284 /*-----------------------------------------------------------------*/
2285 void pCodeReadCodeTable(void)
2289 fprintf(stderr, " %s\n",__FUNCTION__);
2291 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2295 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2296 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2297 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2298 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2300 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2301 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2302 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2303 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2308 /*-----------------------------------------------------------------*/
2309 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2310 /*-----------------------------------------------------------------*/
2311 void addpCode2pBlock(pBlock *pb, pCode *pc)
2318 /* If this is the first pcode to be added to a block that
2319 * was initialized with a NULL pcode, then go ahead and
2320 * make this pcode the head and tail */
2321 pb->pcHead = pb->pcTail = pc;
2324 pb->pcTail->next = pc;
2326 pc->prev = pb->pcTail;
2333 /*-----------------------------------------------------------------*/
2334 /* addpBlock - place a pBlock into the pFile */
2335 /*-----------------------------------------------------------------*/
2336 void addpBlock(pBlock *pb)
2338 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2341 /* First time called, we'll pass through here. */
2342 //_ALLOC(the_pFile,sizeof(pFile));
2343 the_pFile = Safe_calloc(1,sizeof(pFile));
2344 the_pFile->pbHead = the_pFile->pbTail = pb;
2345 the_pFile->functions = NULL;
2349 the_pFile->pbTail->next = pb;
2350 pb->prev = the_pFile->pbTail;
2352 the_pFile->pbTail = pb;
2355 /*-----------------------------------------------------------------*/
2356 /* removepBlock - remove a pBlock from the pFile */
2357 /*-----------------------------------------------------------------*/
2358 void removepBlock(pBlock *pb)
2366 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2368 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2371 if(pbs == the_pFile->pbHead)
2372 the_pFile->pbHead = pbs->next;
2374 if (pbs == the_pFile->pbTail)
2375 the_pFile->pbTail = pbs->prev;
2378 pbs->next->prev = pbs->prev;
2381 pbs->prev->next = pbs->next;
2388 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2392 /*-----------------------------------------------------------------*/
2393 /* printpCode - write the contents of a pCode to a file */
2394 /*-----------------------------------------------------------------*/
2395 void printpCode(FILE *of, pCode *pc)
2406 fprintf(of,"warning - unable to print pCode\n");
2409 /*-----------------------------------------------------------------*/
2410 /* printpBlock - write the contents of a pBlock to a file */
2411 /*-----------------------------------------------------------------*/
2412 void printpBlock(FILE *of, pBlock *pb)
2422 for(pc = pb->pcHead; pc; pc = pc->next)
2427 /*-----------------------------------------------------------------*/
2429 /* pCode processing */
2433 /*-----------------------------------------------------------------*/
2435 void unlinkpCode(pCode *pc)
2441 fprintf(stderr,"Unlinking: ");
2442 printpCode(stderr, pc);
2445 pc->prev->next = pc->next;
2447 pc->next->prev = pc->prev;
2449 pc->prev = pc->next = NULL;
2453 /*-----------------------------------------------------------------*/
2454 /*-----------------------------------------------------------------*/
2456 static void genericDestruct(pCode *pc)
2462 /* For instructions, tell the register (if there's one used)
2463 * that it's no longer needed */
2464 regs *reg = getRegFromInstruction(pc);
2466 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2469 /* Instead of deleting the memory used by this pCode, mark
2470 * the object as bad so that if there's a pointer to this pCode
2471 * dangling around somewhere then (hopefully) when the type is
2472 * checked we'll catch it.
2477 addpCode2pBlock(pb_dead_pcodes, pc);
2484 /*-----------------------------------------------------------------*/
2485 /*-----------------------------------------------------------------*/
2486 void pBlockRegs(FILE *of, pBlock *pb)
2491 r = setFirstItem(pb->tregisters);
2493 r = setNextItem(pb->tregisters);
2498 /*-----------------------------------------------------------------*/
2499 /*-----------------------------------------------------------------*/
2500 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2505 int use_buffer = 1; // copy the string to the passed buffer pointer
2510 use_buffer = 0; // Don't bother copying the string to the buffer.
2514 switch(pcop->type) {
2518 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2521 //return PCOR(pcop)->r->name;
2525 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2528 SAFE_snprintf(&buffer,&size,"%s",r->name);
2538 if(PCOI(pcop)->_const) {
2540 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2541 switch(PCOI(pcop)->offset) {
2543 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2546 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2549 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2552 8 * PCOI(pcop)->offset );
2555 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2558 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2559 SAFE_snprintf(&s,&size,"(%s + %d)",
2561 PCOI(pcop)->index );
2563 switch(PCOI(pcop)->offset) {
2565 SAFE_snprintf(&s,&size,"%s",pcop->name);
2568 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2571 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2580 //size = sizeof(buffer);
2581 if( PCOR(pcop)->instance) {
2582 SAFE_snprintf(&s,&size,"(%s + %d)",
2584 PCOR(pcop)->instance );
2585 //fprintf(stderr,"PO_DIR %s\n",buffer);
2587 SAFE_snprintf(&s,&size,"%s",pcop->name);
2593 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2602 return "NO operand";
2606 /*-----------------------------------------------------------------*/
2607 /*-----------------------------------------------------------------*/
2608 static char *get_op_from_instruction( pCodeInstruction *pcc)
2612 return get_op(pcc->pcop,NULL,0);
2614 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2615 return ("ERROR Null: "__FUNCTION__);
2617 return ("ERROR Null: get_op_from_instruction");
2621 /*-----------------------------------------------------------------*/
2622 /*-----------------------------------------------------------------*/
2623 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2626 fprintf(of,"pcodeopprint- not implemented\n");
2629 /*-----------------------------------------------------------------*/
2630 /*-----------------------------------------------------------------*/
2631 char *pCode2str(char *str, size_t size, pCode *pc)
2639 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2641 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2643 if(PCI(pc)->isBitInst) {
2644 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2645 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2646 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2647 PCI(pc)->pcop->name ,
2648 PCI(pc)->pcop->name );
2650 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2651 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2652 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2653 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2655 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2656 //PCI(pc)->pcop->t.bit );
2659 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2660 if( PCI(pc)->num_ops == 2)
2661 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2663 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2666 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2668 if( PCI(pc)->num_ops == 2)
2669 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2677 /* assuming that comment ends with a \n */
2678 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2682 /* assuming that inline code ends with a \n */
2683 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2687 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2690 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2693 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2696 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2699 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2703 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2710 /*-----------------------------------------------------------------*/
2711 /* genericPrint - the contents of a pCode to a file */
2712 /*-----------------------------------------------------------------*/
2713 static void genericPrint(FILE *of, pCode *pc)
2721 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2725 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2729 // If the opcode has a label, print that first
2731 pBranch *pbl = PCI(pc)->label;
2732 while(pbl && pbl->pc) {
2733 if(pbl->pc->type == PC_LABEL)
2734 pCodePrintLabel(of, pbl->pc);
2740 genericPrint(of,PCODE(PCI(pc)->cline));
2745 pCode2str(str, 256, pc);
2747 fprintf(of,"%s",str);
2751 fprintf(of, "\t;key=%03x",pc->seq);
2753 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2758 pBranch *dpb = pc->to; // debug
2760 switch ( dpb->pc->type) {
2762 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2765 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2768 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2771 fprintf(of, "\t;flow");
2785 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2786 if(PCW(pc)->pci.label)
2787 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2789 if(PCW(pc)->operand) {
2790 fprintf(of,";\toperand ");
2791 pCodeOpPrint(of,PCW(pc)->operand );
2797 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2798 if(PCFL(pc)->ancestor)
2799 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2806 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2810 fprintf(of,"unknown pCode type %d\n",pc->type);
2815 /*-----------------------------------------------------------------*/
2816 /* pCodePrintFunction - prints function begin/end */
2817 /*-----------------------------------------------------------------*/
2819 static void pCodePrintFunction(FILE *of, pCode *pc)
2825 if( ((pCodeFunction *)pc)->modname)
2826 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2828 if(PCF(pc)->fname) {
2829 pBranch *exits = PCF(pc)->to;
2831 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2834 exits = exits->next;
2837 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2840 if((PCF(pc)->from &&
2841 PCF(pc)->from->pc->type == PC_FUNCTION &&
2842 PCF(PCF(pc)->from->pc)->fname) )
2843 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2845 fprintf(of,"; exit point [can't find entry point]\n");
2848 /*-----------------------------------------------------------------*/
2849 /* pCodePrintLabel - prints label */
2850 /*-----------------------------------------------------------------*/
2852 static void pCodePrintLabel(FILE *of, pCode *pc)
2859 fprintf(of,"%s\n",PCL(pc)->label);
2860 else if (PCL(pc)->key >=0)
2861 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2863 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2866 /*-----------------------------------------------------------------*/
2867 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2868 /* remove it if it is found. */
2869 /*-----------------------------------------------------------------*/
2870 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2877 if(pcl->type == PC_OPCODE)
2878 b = PCI(pcl)->label;
2880 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2885 //fprintf (stderr, "%s \n",__FUNCTION__);
2886 //pcl->print(stderr,pcl);
2887 //pc->print(stderr,pc);
2890 //fprintf (stderr, "found label\n");
2894 bprev->next = b->next; /* Not first pCode in chain */
2898 PCI(pcl)->label = b->next; /* First pCode in chain */
2901 return; /* A label can't occur more than once */
2909 /*-----------------------------------------------------------------*/
2910 /*-----------------------------------------------------------------*/
2911 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2930 /*-----------------------------------------------------------------*/
2931 /* pBranchLink - given two pcodes, this function will link them */
2932 /* together through their pBranches */
2933 /*-----------------------------------------------------------------*/
2934 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2938 // Declare a new branch object for the 'from' pCode.
2940 //_ALLOC(b,sizeof(pBranch));
2941 b = Safe_calloc(1,sizeof(pBranch));
2942 b->pc = PCODE(t); // The link to the 'to' pCode.
2945 f->to = pBranchAppend(f->to,b);
2947 // Now do the same for the 'to' pCode.
2949 //_ALLOC(b,sizeof(pBranch));
2950 b = Safe_calloc(1,sizeof(pBranch));
2954 t->from = pBranchAppend(t->from,b);
2959 /*-----------------------------------------------------------------*/
2960 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2962 /*-----------------------------------------------------------------*/
2963 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2976 /*-----------------------------------------------------------------*/
2977 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2978 /*-----------------------------------------------------------------*/
2979 static void pCodeUnlink(pCode *pc)
2984 if(!pc->prev || !pc->next) {
2985 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2989 /* first remove the pCode from the chain */
2990 pc->prev->next = pc->next;
2991 pc->next->prev = pc->prev;
2993 /* Now for the hard part... */
2995 /* Remove the branches */
2999 pc1 = pb1->pc; /* Get the pCode that branches to the
3000 * one we're unlinking */
3002 /* search for the link back to this pCode (the one we're
3004 if(pb2 = pBranchFind(pc1->to,pc)) {
3005 pb2->pc = pc->to->pc; // make the replacement
3007 /* if the pCode we're unlinking contains multiple 'to'
3008 * branches (e.g. this a skip instruction) then we need
3009 * to copy these extra branches to the chain. */
3011 pBranchAppend(pb2, pc->to->next);
3020 /*-----------------------------------------------------------------*/
3021 /*-----------------------------------------------------------------*/
3023 static void genericAnalyze(pCode *pc)
3033 // Go through the pCodes that are in pCode chain and link
3034 // them together through the pBranches. Note, the pCodes
3035 // are linked together as a contiguous stream like the
3036 // assembly source code lines. The linking here mimics this
3037 // except that comments are not linked in.
3039 pCode *npc = pc->next;
3041 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3042 pBranchLink(pc,npc);
3047 /* reached the end of the pcode chain without finding
3048 * an instruction we could link to. */
3052 fprintf(stderr,"analyze PC_FLOW\n");
3056 fprintf(stderr,,";A bad pCode is being used\n");
3062 /*-----------------------------------------------------------------*/
3063 /*-----------------------------------------------------------------*/
3064 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3068 if(pc->type == PC_LABEL) {
3069 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3072 if(pc->type == PC_OPCODE) {
3073 pbr = PCI(pc)->label;
3075 if(pbr->pc->type == PC_LABEL) {
3076 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3086 /*-----------------------------------------------------------------*/
3087 /*-----------------------------------------------------------------*/
3088 int checkLabel(pCode *pc)
3092 if(pc && isPCI(pc)) {
3093 pbr = PCI(pc)->label;
3095 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3105 /*-----------------------------------------------------------------*/
3106 /* findLabelinpBlock - Search the pCode for a particular label */
3107 /*-----------------------------------------------------------------*/
3108 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3115 for(pc = pb->pcHead; pc; pc = pc->next)
3116 if(compareLabel(pc,pcop_label))
3122 /*-----------------------------------------------------------------*/
3123 /* findLabel - Search the pCode for a particular label */
3124 /*-----------------------------------------------------------------*/
3125 pCode * findLabel(pCodeOpLabel *pcop_label)
3133 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3134 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3138 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3142 /*-----------------------------------------------------------------*/
3143 /* findNextpCode - given a pCode, find the next of type 'pct' */
3144 /* in the linked list */
3145 /*-----------------------------------------------------------------*/
3146 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3159 /*-----------------------------------------------------------------*/
3160 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3161 /* in the linked list */
3162 /*-----------------------------------------------------------------*/
3163 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3175 /*-----------------------------------------------------------------*/
3176 /* findNextInstruction - given a pCode, find the next instruction */
3177 /* in the linked list */
3178 /*-----------------------------------------------------------------*/
3179 pCode * findNextInstruction(pCode *pci)
3184 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3188 fprintf(stderr,"findNextInstruction: ");
3189 printpCode(stderr, pc);
3194 //fprintf(stderr,"Couldn't find instruction\n");
3198 /*-----------------------------------------------------------------*/
3199 /* findNextInstruction - given a pCode, find the next instruction */
3200 /* in the linked list */
3201 /*-----------------------------------------------------------------*/
3202 pCode * findPrevInstruction(pCode *pci)
3204 return findPrevpCode(pci, PC_OPCODE);
3207 /*-----------------------------------------------------------------*/
3208 /* findFunctionEnd - given a pCode find the end of the function */
3209 /* that contains it */
3210 /*-----------------------------------------------------------------*/
3211 pCode * findFunctionEnd(pCode *pc)
3215 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3221 fprintf(stderr,"Couldn't find function end\n");
3226 /*-----------------------------------------------------------------*/
3227 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3228 /* instruction with which it is associated. */
3229 /*-----------------------------------------------------------------*/
3230 static void AnalyzeLabel(pCode *pc)
3239 static void AnalyzeGOTO(pCode *pc)
3242 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3246 static void AnalyzeSKIP(pCode *pc)
3249 pBranchLink(pc,findNextInstruction(pc->next));
3250 pBranchLink(pc,findNextInstruction(pc->next->next));
3254 static void AnalyzeRETURN(pCode *pc)
3257 // branch_link(pc,findFunctionEnd(pc->next));
3263 /*-----------------------------------------------------------------*/
3264 /*-----------------------------------------------------------------*/
3265 regs * getRegFromInstruction(pCode *pc)
3271 PCI(pc)->num_ops == 0 )
3274 switch(PCI(pc)->pcop->type) {
3277 return PCOR(PCI(pc)->pcop)->r;
3279 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3283 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3284 return PCOR(PCI(pc)->pcop)->r;
3287 if(PCOI(PCI(pc)->pcop)->r)
3288 return (PCOI(PCI(pc)->pcop)->r);
3290 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3291 return dirregWithName(PCI(pc)->pcop->name);
3292 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3295 return PCOR(PCI(pc)->pcop)->r;
3298 //fprintf(stderr, "getRegFromInstruction - dir\n");
3299 return PCOR(PCI(pc)->pcop)->r;
3301 //fprintf(stderr, "getRegFromInstruction - literal\n");
3305 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3306 //genericPrint(stderr, pc);
3314 /*-----------------------------------------------------------------*/
3315 /*-----------------------------------------------------------------*/
3317 void AnalyzepBlock(pBlock *pb)
3324 /* Find all of the registers used in this pBlock
3325 * by looking at each instruction and examining it's
3328 for(pc = pb->pcHead; pc; pc = pc->next) {
3330 /* Is this an instruction with operands? */
3331 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3333 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3335 /* Loop through all of the registers declared so far in
3336 this block and see if we find this one there */
3338 regs *r = setFirstItem(pb->tregisters);
3341 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3342 PCOR(PCI(pc)->pcop)->r = r;
3345 r = setNextItem(pb->tregisters);
3349 /* register wasn't found */
3350 //r = Safe_calloc(1, sizeof(regs));
3351 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3352 //addSet(&pb->tregisters, r);
3353 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3354 //PCOR(PCI(pc)->pcop)->r = r;
3355 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3357 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3360 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3361 if(PCOR(PCI(pc)->pcop)->r) {
3362 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3363 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3365 if(PCI(pc)->pcop->name)
3366 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3368 fprintf(stderr,"ERROR: NULL register\n");
3377 /*-----------------------------------------------------------------*/
3379 /*-----------------------------------------------------------------*/
3380 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3382 void InsertpFlow(pCode *pc, pCode **pflow)
3385 PCFL(*pflow)->end = pc;
3387 if(!pc || !pc->next)
3390 *pflow = newpCodeFlow();
3391 pCodeInsertAfter(pc, *pflow);
3394 /*-----------------------------------------------------------------*/
3395 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3396 /* the flow blocks. */
3398 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3399 * point the instruction flow changes.
3401 /*-----------------------------------------------------------------*/
3402 void BuildFlow(pBlock *pb)
3405 pCode *last_pci=NULL;
3412 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3413 /* Insert a pCodeFlow object at the beginning of a pBlock */
3415 InsertpFlow(pb->pcHead, &pflow);
3417 //pflow = newpCodeFlow(); /* Create a new Flow object */
3418 //pflow->next = pb->pcHead; /* Make the current head the next object */
3419 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3420 //pb->pcHead = pflow; /* Make the Flow object the head */
3423 for( pc = findNextInstruction(pb->pcHead);
3425 pc=findNextInstruction(pc)) {
3428 PCI(pc)->pcflow = PCFL(pflow);
3430 //fprintf(stderr," build: ");
3431 //pflow->print(stderr,pflow);
3433 if( PCI(pc)->isSkip) {
3435 /* The two instructions immediately following this one
3436 * mark the beginning of a new flow segment */
3438 while(pc && PCI(pc)->isSkip) {
3440 PCI(pc)->pcflow = PCFL(pflow);
3444 InsertpFlow(pc, &pflow);
3445 pc=findNextInstruction(pc->next);
3453 PCI(pc)->pcflow = PCFL(pflow);
3455 InsertpFlow(pc, &pflow);
3457 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3459 InsertpFlow(pc, &pflow);
3462 } else if (checkLabel(pc)) {
3464 /* This instruction marks the beginning of a
3465 * new flow segment */
3470 /* If the previous pCode is not a flow object, then
3471 * insert a new flow object. (This check prevents
3472 * two consecutive flow objects from being insert in
3473 * the case where a skip instruction preceeds an
3474 * instruction containing a label.) */
3476 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3477 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3479 PCI(pc)->pcflow = PCFL(pflow);
3486 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3488 PCFL(pflow)->end = pb->pcTail;
3491 /*-------------------------------------------------------------------*/
3492 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3493 /* the flow blocks. */
3495 * unBuildFlow removes pCodeFlow objects from a pCode chain
3497 /*-----------------------------------------------------------------*/
3498 void unBuildFlow(pBlock *pb)
3513 if(PCI(pc)->pcflow) {
3514 //free(PCI(pc)->pcflow);
3515 PCI(pc)->pcflow = NULL;
3518 } else if(isPCFL(pc) )
3527 /*-----------------------------------------------------------------*/
3528 /*-----------------------------------------------------------------*/
3529 void dumpCond(int cond)
3532 static char *pcc_str[] = {
3546 int ncond = sizeof(pcc_str) / sizeof(char *);
3549 fprintf(stderr, "0x%04X\n",cond);
3551 for(i=0,j=1; i<ncond; i++, j<<=1)
3553 fprintf(stderr, " %s\n",pcc_str[i]);
3557 /*-----------------------------------------------------------------*/
3558 /*-----------------------------------------------------------------*/
3559 void FlowStats(pCodeFlow *pcflow)
3567 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3569 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3572 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3577 fprintf(stderr, " FlowStats inCond: ");
3578 dumpCond(pcflow->inCond);
3579 fprintf(stderr, " FlowStats outCond: ");
3580 dumpCond(pcflow->outCond);
3584 /*-----------------------------------------------------------------*
3585 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3586 * if it affects the banking bits.
3588 * return: -1 == Banking bits are unaffected by this pCode.
3590 * return: > 0 == Banking bits are affected.
3592 * If the banking bits are affected, then the returned value describes
3593 * which bits are affected and how they're affected. The lower half
3594 * of the integer maps to the bits that are affected, the upper half
3595 * to whether they're set or cleared.
3597 *-----------------------------------------------------------------*/
3598 #define SET_BANK_BIT (1 << 16)
3599 #define CLR_BANK_BIT 0
3601 int isBankInstruction(pCode *pc)
3609 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3611 /* Check to see if the register banks are changing */
3612 if(PCI(pc)->isModReg) {
3614 pCodeOp *pcop = PCI(pc)->pcop;
3615 switch(PCI(pc)->op) {
3618 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3619 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3620 return SET_BANK_BIT | PIC_RP0_BIT;
3623 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3624 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3625 return CLR_BANK_BIT | PIC_RP0_BIT;
3630 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3631 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3632 return CLR_BANK_BIT | PIC_RP1_BIT;
3634 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3635 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3636 return CLR_BANK_BIT | PIC_RP1_BIT;
3640 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3641 //genericPrint(stderr, pc);
3652 /*-----------------------------------------------------------------*/
3653 /*-----------------------------------------------------------------*/
3654 void FillFlow(pCodeFlow *pcflow)
3663 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3665 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3668 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3675 isBankInstruction(pc);
3677 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3681 fprintf(stderr, " FillFlow - Bad end of flow\n");
3683 fprintf(stderr, " FillFlow - Ending flow with\n ");
3684 pc->print(stderr,pc);
3687 fprintf(stderr, " FillFlow inCond: ");
3688 dumpCond(pcflow->inCond);
3689 fprintf(stderr, " FillFlow outCond: ");
3690 dumpCond(pcflow->outCond);
3694 /*-----------------------------------------------------------------*/
3695 /*-----------------------------------------------------------------*/
3696 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3698 pCodeFlowLink *fromLink, *toLink;
3700 if(!from || !to || !to->pcflow || !from->pcflow)
3703 fromLink = newpCodeFlowLink(from->pcflow);
3704 toLink = newpCodeFlowLink(to->pcflow);
3706 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3707 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3711 /*-----------------------------------------------------------------*
3712 * void LinkFlow(pBlock *pb)
3714 * In BuildFlow, the PIC code has been partitioned into contiguous
3715 * non-branching segments. In LinkFlow, we determine the execution
3716 * order of these segments. For example, if one of the segments ends
3717 * with a skip, then we know that there are two possible flow segments
3718 * to which control may be passed.
3719 *-----------------------------------------------------------------*/
3720 void LinkFlow(pBlock *pb)
3726 //fprintf(stderr,"linkflow \n");
3728 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3730 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3733 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3735 //fprintf(stderr," link: ");
3736 //pcflow->print(stderr,pcflow);
3738 //FillFlow(PCFL(pcflow));
3740 pc = PCFL(pcflow)->end;
3742 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3743 if(isPCI_SKIP(pc)) {
3744 //fprintf(stderr, "ends with skip\n");
3745 //pc->print(stderr,pc);
3746 pct=findNextInstruction(pc->next);
3747 LinkFlow_pCode(PCI(pc),PCI(pct));
3748 pct=findNextInstruction(pct->next);
3749 LinkFlow_pCode(PCI(pc),PCI(pct));
3753 if(isPCI_BRANCH(pc)) {
3754 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3756 //fprintf(stderr, "ends with branch\n ");
3757 //pc->print(stderr,pc);
3759 if(!(pcol && isPCOLAB(pcol))) {
3760 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3761 pc->print(stderr,pc);
3762 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3767 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3768 LinkFlow_pCode(PCI(pc),PCI(pct));
3770 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3771 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3772 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3778 //fprintf(stderr, "ends with non-branching instruction:\n");
3779 //pc->print(stderr,pc);
3781 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3787 //fprintf(stderr, "ends with unknown\n");
3788 //pc->print(stderr,pc);
3792 //fprintf(stderr, "ends with nothing: ERROR\n");
3796 /*-----------------------------------------------------------------*/
3797 /*-----------------------------------------------------------------*/
3799 /*-----------------------------------------------------------------*/
3800 /*-----------------------------------------------------------------*/
3801 int isPCinFlow(pCode *pc, pCode *pcflow)
3807 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3810 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3816 /*-----------------------------------------------------------------*/
3817 /*-----------------------------------------------------------------*/
3818 void BanksUsedFlow2(pCode *pcflow)
3827 if(!isPCFL(pcflow)) {
3828 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3832 pc = findNextInstruction(pcflow->next);
3834 PCFL(pcflow)->lastBank = -1;
3836 while(isPCinFlow(pc,pcflow)) {
3838 int bank_selected = isBankInstruction(pc);
3840 //if(PCI(pc)->pcflow)
3841 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3843 if(bank_selected > 0) {
3844 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3846 /* This instruction is modifying banking bits before accessing registers */
3848 PCFL(pcflow)->firstBank = -1;
3850 if(PCFL(pcflow)->lastBank == -1)
3851 PCFL(pcflow)->lastBank = 0;
3853 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3854 if(bank_selected & SET_BANK_BIT)
3855 PCFL(pcflow)->lastBank |= bank;
3859 reg = getRegFromInstruction(pc);
3861 if(reg && !isREGinBank(reg, bank)) {
3862 int allbanks = REGallBanks(reg);
3864 PCFL(pcflow)->firstBank = allbanks;
3866 PCFL(pcflow)->lastBank = allbanks;
3873 pc = findNextInstruction(pc->next);
3876 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3877 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3882 /*-----------------------------------------------------------------*/
3883 /*-----------------------------------------------------------------*/
3884 void BanksUsedFlow(pBlock *pb)
3889 //pb->pcHead->print(stderr, pb->pcHead);
3891 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3892 //pcflow->print(stderr,pcflow);
3894 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3896 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3898 BanksUsedFlow2(pcflow);
3904 /*-----------------------------------------------------------------*/
3905 /*-----------------------------------------------------------------*/
3906 void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
3914 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3916 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3917 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3920 /* insert the bank switch after this pc instruction */
3921 pCode *pcnext = findNextInstruction(pc);
3922 pCodeInsertAfter(pc, new_pc);
3927 pCodeInsertAfter(pc->prev, new_pc);
3929 /* Move the label, if there is one */
3931 if(PCI(pc)->label) {
3932 PCI(new_pc)->label = PCI(pc)->label;
3933 PCI(pc)->label = NULL;
3936 /* The new instruction has the same pcflow block */
3937 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3940 /*-----------------------------------------------------------------*/
3941 /*-----------------------------------------------------------------*/
3942 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3953 pc = findNextInstruction(pcfl->pc.next);
3955 while(isPCinFlow(pc,PCODE(pcfl))) {
3957 reg = getRegFromInstruction(pc);
3960 fprintf(stderr, " %s ",reg->name);
3961 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3966 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
3967 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
3970 /* Examine the instruction before this one to make sure it is
3971 * not a skip type instruction */
3972 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3974 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3978 reg_bank = (reg) ? REG_BANK(reg) : 0;
3980 b = cur_bank ^ reg_bank;
3982 //fprintf(stderr, "Cool! can switch banks\n");
3983 cur_bank = reg_bank;
3988 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3991 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3992 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3996 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
3997 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
3999 insertBankSwitch(0, pc, -1, -1);
4005 //fprintf(stderr, "Bummer can't switch banks\n");
4011 pc = findNextInstruction(pc->next);
4015 if(pcprev && cur_bank) {
4016 /* Brute force - make sure that we point to bank 0 at the
4017 * end of each flow block */
4018 new_pc = newpCode(POC_BCF,
4019 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4020 pCodeInsertAfter(pcprev, new_pc);
4026 /*-----------------------------------------------------------------*/
4027 /*int compareBankFlow - compare the banking requirements between */
4029 /*-----------------------------------------------------------------*/
4030 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4033 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4036 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4039 if(pcflow->firstBank == -1)
4043 if(pcflowLink->pcflow->firstBank == -1) {
4044 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4045 pcflowLink->pcflow->to :
4046 pcflowLink->pcflow->from);
4047 return compareBankFlow(pcflow, pctl, toORfrom);
4051 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4054 pcflowLink->bank_conflict++;
4055 pcflowLink->pcflow->FromConflicts++;
4056 pcflow->ToConflicts++;
4059 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4062 pcflowLink->bank_conflict++;
4063 pcflowLink->pcflow->ToConflicts++;
4064 pcflow->FromConflicts++;
4068 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4069 pcflowLink->pcflow->pc.seq,
4070 pcflowLink->pcflow->FromConflicts,
4071 pcflowLink->pcflow->ToConflicts);
4076 /*-----------------------------------------------------------------*/
4077 /*-----------------------------------------------------------------*/
4078 void FixBankFlow(pBlock *pb)
4082 pCodeFlowLink *pcfl;
4084 pCode *pcflow_max_To=NULL;
4085 pCode *pcflow_max_From=NULL;
4086 int max_ToConflicts=0;
4087 int max_FromConflicts=0;
4089 //fprintf(stderr,"Fix Bank flow \n");
4090 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4094 First loop through all of the flow objects in this pcode block
4095 and fix the ones that have banking conflicts between the
4099 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4101 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4103 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4105 if(!isPCFL(pcflow)) {
4106 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4110 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4111 PCFL(pcflow)->firstBank >= 0 &&
4112 PCFL(pcflow)->lastBank >= 0 ) {
4114 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4115 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4117 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4118 BanksUsedFlow2(pcflow);
4123 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4125 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4127 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4132 if(!isPCFL(pcflow)) {
4133 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4137 PCFL(pcflow)->FromConflicts = 0;
4138 PCFL(pcflow)->ToConflicts = 0;
4143 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4144 pcfl = setFirstItem(PCFL(pcflow)->from);
4147 pc = PCODE(pcfl->pcflow);
4150 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4151 pc->print(stderr,pc);
4154 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4157 pcfl=setNextItem(PCFL(pcflow)->from);
4160 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4161 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4163 FixRegisterBankingInFlow(PCFL(pcflow),0);
4164 BanksUsedFlow2(pcflow);
4166 continue; /* Don't need to check the flow from here - it's already been fixed */
4173 pcfl = setFirstItem(PCFL(pcflow)->to);
4176 pc = PCODE(pcfl->pcflow);
4178 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4179 pc->print(stderr,pc);
4182 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4185 pcfl=setNextItem(PCFL(pcflow)->to);
4188 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4189 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4191 FixRegisterBankingInFlow(PCFL(pcflow),0);
4192 BanksUsedFlow2(pcflow);
4197 Loop through the flow objects again and find the ones with the
4201 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4203 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4205 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4206 pcflow_max_To = pcflow;
4208 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4209 pcflow_max_From = pcflow;
4213 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4214 PCFL(pcflow_max_To)->pc.seq,
4215 PCFL(pcflow_max_To)->ToConflicts);
4218 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4219 PCFL(pcflow_max_From)->pc.seq,
4220 PCFL(pcflow_max_From)->FromConflicts);
4224 /*-----------------------------------------------------------------*/
4225 /*-----------------------------------------------------------------*/
4226 void DumpFlow(pBlock *pb)
4230 pCodeFlowLink *pcfl;
4233 fprintf(stderr,"Dump flow \n");
4234 pb->pcHead->print(stderr, pb->pcHead);
4236 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4237 pcflow->print(stderr,pcflow);
4239 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4241 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4243 if(!isPCFL(pcflow)) {
4244 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4247 fprintf(stderr,"dumping: ");
4248 pcflow->print(stderr,pcflow);
4249 FlowStats(PCFL(pcflow));
4251 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4253 pc = PCODE(pcfl->pcflow);
4255 fprintf(stderr, " from seq %d:\n",pc->seq);
4257 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4258 pc->print(stderr,pc);
4263 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4265 pc = PCODE(pcfl->pcflow);
4267 fprintf(stderr, " to seq %d:\n",pc->seq);
4269 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4270 pc->print(stderr,pc);
4279 /*-----------------------------------------------------------------*/
4280 /*-----------------------------------------------------------------*/
4281 int OptimizepBlock(pBlock *pb)
4286 if(!pb || !peepOptimizing)
4289 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4291 for(pc = pb->pcHead; pc; pc = pc->next)
4292 matches += pCodePeepMatchRule(pc);
4295 pc = findNextInstruction(pb->pcHead);
4303 if(pCodePeepMatchRule(pc)) {
4308 pc = findNextInstruction(pcprev->next);
4310 pc = findNextInstruction(pb->pcHead);
4312 pc = findNextInstruction(pc->next);
4316 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4321 /*-----------------------------------------------------------------*/
4322 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4323 /*-----------------------------------------------------------------*/
4324 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4328 for(pc = pcs; pc; pc = pc->next) {
4330 if((pc->type == PC_OPCODE) &&
4332 (PCI(pc)->pcop->type == PO_LABEL) &&
4333 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4341 /*-----------------------------------------------------------------*/
4342 /*-----------------------------------------------------------------*/
4343 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4350 (PCI(pc)->pcop->type == PO_LABEL)) {
4352 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4354 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4356 free(pcol->pcop.name);
4358 /* If the key is negative, then we (probably) have a label to
4359 * a function and the name is already defined */
4362 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4366 //sprintf(buffer,"_%05d_DS_",pcl->key);
4368 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4370 pcol->pcop.name = Safe_strdup(s);
4371 pcol->key = pcl->key;
4372 //pc->print(stderr,pc);
4379 /*-----------------------------------------------------------------*/
4380 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4381 /* pCode chain if they're not used. */
4382 /*-----------------------------------------------------------------*/
4383 void pBlockRemoveUnusedLabels(pBlock *pb)
4385 pCode *pc; pCodeLabel *pcl;
4390 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4392 pBranch *pbr = PCI(pc)->label;
4393 if(pbr && pbr->next) {
4394 pCode *pcd = pb->pcHead;
4396 //fprintf(stderr, "multiple labels\n");
4397 //pc->print(stderr,pc);
4402 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4403 //fprintf(stderr,"Used by:\n");
4404 //pcd->print(stderr,pcd);
4406 exchangeLabels(PCL(pbr->pc),pcd);
4415 for(pc = pb->pcHead; pc; pc = pc->next) {
4417 if(isPCL(pc)) // pc->type == PC_LABEL)
4419 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4420 pcl = PCL(PCI(pc)->label->pc);
4423 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4425 /* This pCode is a label, so search the pBlock to see if anyone
4428 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4429 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4430 /* Couldn't find an instruction that refers to this label
4431 * So, unlink the pCode label from it's pCode chain
4432 * and destroy the label */
4433 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4435 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4436 if(pc->type == PC_LABEL) {
4438 pCodeLabelDestruct(pc);
4440 unlinkpCodeFromBranch(pc, PCODE(pcl));
4441 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4452 /*-----------------------------------------------------------------*/
4453 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4454 /* chain and put them into pBranches that are */
4455 /* associated with the appropriate pCode */
4457 /*-----------------------------------------------------------------*/
4458 void pBlockMergeLabels(pBlock *pb)
4461 pCode *pc, *pcnext=NULL;
4466 /* First, Try to remove any unused labels */
4467 //pBlockRemoveUnusedLabels(pb);
4469 /* Now loop through the pBlock and merge the labels with the opcodes */
4472 // for(pc = pb->pcHead; pc; pc = pc->next) {
4475 pCode *pcn = pc->next;
4477 if(pc->type == PC_LABEL) {
4479 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4480 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4481 if((pcnext = findNextInstruction(pc) )) {
4483 // Unlink the pCode label from it's pCode chain
4486 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4487 // And link it into the instruction's pBranch labels. (Note, since
4488 // it's possible to have multiple labels associated with one instruction
4489 // we must provide a means to accomodate the additional labels. Thus
4490 // the labels are placed into the singly-linked list "label" as
4491 // opposed to being a single member of the pCodeInstruction.)
4493 //_ALLOC(pbr,sizeof(pBranch));
4494 pbr = Safe_calloc(1,sizeof(pBranch));
4498 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4501 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4503 } else if(pc->type == PC_CSOURCE) {
4505 /* merge the source line symbolic info into the next instruction */
4506 if((pcnext = findNextInstruction(pc) )) {
4508 // Unlink the pCode label from it's pCode chain
4510 PCI(pcnext)->cline = PCCS(pc);
4511 //fprintf(stderr, "merging CSRC\n");
4512 //genericPrint(stderr,pcnext);
4518 pBlockRemoveUnusedLabels(pb);
4522 /*-----------------------------------------------------------------*/
4523 /*-----------------------------------------------------------------*/
4524 int OptimizepCode(char dbName)
4526 #define MAX_PASSES 4
4535 DFPRINTF((stderr," Optimizing pCode\n"));
4539 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4540 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4541 matches += OptimizepBlock(pb);
4544 while(matches && ++passes < MAX_PASSES);
4549 /*-----------------------------------------------------------------*/
4550 /* popCopyGPR2Bit - copy a pcode operator */
4551 /*-----------------------------------------------------------------*/
4553 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4557 pcop = newpCodeOpBit(pc->name, bitval, 0);
4559 if( !( (pcop->type == PO_LABEL) ||
4560 (pcop->type == PO_LITERAL) ||
4561 (pcop->type == PO_STR) ))
4562 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4570 /*-----------------------------------------------------------------*/
4571 /*-----------------------------------------------------------------*/
4572 int InstructionRegBank(pCode *pc)
4576 if( (reg = getRegFromInstruction(pc)) == NULL)
4579 return REG_BANK(reg);
4584 /*-----------------------------------------------------------------*/
4585 /*-----------------------------------------------------------------*/
4586 void FixRegisterBanking(pBlock *pb)
4597 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4598 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4601 /* loop through all of the flow blocks with in one pblock */
4603 //fprintf(stderr,"Register banking\n");
4606 /* at this point, pc should point to a PC_FLOW object */
4609 /* for each flow block, determine the register banking
4614 //genericPrint(stderr, pc);
4616 reg = getRegFromInstruction(pc);
4619 fprintf(stderr, " %s ",reg->name);
4620 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
4621 reg->address,REG_BANK(reg),reg->isBitField);
4626 if( ( (reg && REG_BANK(reg)!=cur_bank) ||
4627 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4631 /* Examine the instruction before this one to make sure it is
4632 * not a skip type instruction */
4633 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4635 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4639 reg_bank = (reg) ? REG_BANK(reg) : 0;
4641 b = cur_bank ^ reg_bank;
4643 cur_bank = reg_bank;
4648 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4651 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4652 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4656 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4657 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4659 insertBankSwitch(0, pc, -1, -1);
4665 //fprintf(stderr, "Bummer can't switch banks\n");
4675 // } while(pc && !(isPCFL(pc)));
4680 if(pcprev && cur_bank) {
4682 int pos = 1; /* Assume that the bank swithc instruction(s)
4683 * are inserted after this instruction */
4685 if((PCI(pcprev)->op == POC_RETLW) ||
4686 (PCI(pcprev)->op == POC_RETURN) ||
4687 (PCI(pcprev)->op == POC_RETFIE)) {
4689 /* oops, a RETURN - we need to switch banks *before* the RETURN */
4695 /* Brute force - make sure that we point to bank 0 at the
4696 * end of each flow block */
4698 switch(cur_bank & 3) {
4702 insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
4705 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4706 insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
4709 insertBankSwitch(pos, pcprev, -1, -1);
4714 new_pc = newpCode(POC_BCF,
4715 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4716 pCodeInsertAfter(pcprev, new_pc);
4719 //fprintf(stderr, "Brute force switch\n");
4728 if(reg && REG_BANK(reg)!=cur_bank) {
4729 //fprintf(stderr,"need to switch banks\n");
4730 /* Examine the instruction before this one to make sure it is
4731 * not a skip type instruction */
4732 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4733 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4734 int b = cur_bank ^ REG_BANK(reg);
4736 cur_bank = REG_BANK(reg);
4742 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4745 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4746 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4750 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
4751 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
4753 insertBankSwitch(0, pc, -1, -1);
4762 void pBlockDestruct(pBlock *pb)
4773 /*-----------------------------------------------------------------*/
4774 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4775 /* name dbName and combine them */
4776 /* into one block */
4777 /*-----------------------------------------------------------------*/
4778 void mergepBlocks(char dbName)
4781 pBlock *pb, *pbmerged = NULL,*pbn;
4783 pb = the_pFile->pbHead;
4785 //fprintf(stderr," merging blocks named %c\n",dbName);
4789 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4790 if( getpBlock_dbName(pb) == dbName) {
4792 //fprintf(stderr," merged block %c\n",dbName);
4797 addpCode2pBlock(pbmerged, pb->pcHead);
4798 /* addpCode2pBlock doesn't handle the tail: */
4799 pbmerged->pcTail = pb->pcTail;
4801 pb->prev->next = pbn;
4803 pbn->prev = pb->prev;
4808 //printpBlock(stderr, pbmerged);
4815 /*-----------------------------------------------------------------*/
4816 /* AnalyzeFlow - Examine the flow of the code and optimize */
4818 /* level 0 == minimal optimization */
4819 /* optimize registers that are used only by two instructions */
4820 /* level 1 == maximal optimization */
4821 /* optimize by looking at pairs of instructions that use the */
4823 /*-----------------------------------------------------------------*/
4825 void AnalyzeFlow(int level)
4827 static int times_called=0;
4835 /* if this is not the first time this function has been called,
4836 then clean up old flow information */
4837 if(times_called++) {
4838 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4841 RegsUnMapLiveRanges();
4847 /* Phase 2 - Flow Analysis - Register Banking
4849 * In this phase, the individual flow blocks are examined
4850 * and register banking is fixed.
4853 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4854 //FixRegisterBanking(pb);
4856 /* Phase 2 - Flow Analysis
4858 * In this phase, the pCode is partition into pCodeFlow
4859 * blocks. The flow blocks mark the points where a continuous
4860 * stream of instructions changes flow (e.g. because of
4861 * a call or goto or whatever).
4864 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4868 /* Phase 2 - Flow Analysis - linking flow blocks
4870 * In this phase, the individual flow blocks are examined
4871 * to determine their order of excution.
4874 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4877 /* Phase 3 - Flow Analysis - Flow Tree
4879 * In this phase, the individual flow blocks are examined
4880 * to determine their order of excution.
4883 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4887 /* Phase x - Flow Analysis - Used Banks
4889 * In this phase, the individual flow blocks are examined
4890 * to determine the Register Banks they use
4893 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4897 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4898 pCodeRegMapLiveRanges(pb);
4900 RemoveUnusedRegisters();
4902 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4903 pCodeRegOptimizeRegUsage(level);
4909 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4913 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4915 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4916 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4917 pcflow = pcflow->next) {
4919 FillFlow(PCFL(pcflow));
4924 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4926 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4927 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4928 pcflow = pcflow->next) {
4930 FlowStats(PCFL(pcflow));
4936 /*-----------------------------------------------------------------*/
4937 /* AnalyzeBanking - Called after the memory addresses have been */
4938 /* assigned to the registers. */
4940 /*-----------------------------------------------------------------*/
4942 void AnalyzeBanking(void)
4946 if(!picIsInitialized()) {
4947 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4948 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4949 fprintf(stderr,"support/scripts/inc2h.pl\n");
4950 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4955 /* Phase x - Flow Analysis - Used Banks
4957 * In this phase, the individual flow blocks are examined
4958 * to determine the Register Banks they use
4964 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4966 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4967 FixRegisterBanking(pb);
4971 /*-----------------------------------------------------------------*/
4972 /* buildCallTree - look at the flow and extract all of the calls */
4974 /*-----------------------------------------------------------------*/
4975 set *register_usage(pBlock *pb);
4977 void buildCallTree(void )
4988 /* Now build the call tree.
4989 First we examine all of the pCodes for functions.
4990 Keep in mind that the function boundaries coincide
4991 with pBlock boundaries.
4993 The algorithm goes something like this:
4994 We have two nested loops. The outer loop iterates
4995 through all of the pBlocks/functions. The inner
4996 loop iterates through all of the pCodes for
4997 a given pBlock. When we begin iterating through
4998 a pBlock, the variable pc_fstart, pCode of the start
4999 of a function, is cleared. We then search for pCodes
5000 of type PC_FUNCTION. When one is encountered, we
5001 initialize pc_fstart to this and at the same time
5002 associate a new pBranch object that signifies a
5003 branch entry. If a return is found, then this signifies
5004 a function exit point. We'll link the pCodes of these
5005 returns to the matching pc_fstart.
5007 When we're done, a doubly linked list of pBranches
5008 will exist. The head of this list is stored in
5009 `the_pFile', which is the meta structure for all
5010 of the pCode. Look at the printCallTree function
5011 on how the pBranches are linked together.
5014 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5015 pCode *pc_fstart=NULL;
5016 for(pc = pb->pcHead; pc; pc = pc->next) {
5018 if (PCF(pc)->fname) {
5020 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5021 //fprintf(stderr," found main \n");
5022 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5026 pbr = Safe_calloc(1,sizeof(pBranch));
5027 pbr->pc = pc_fstart = pc;
5030 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5032 // Here's a better way of doing the same:
5033 addSet(&pb->function_entries, pc);
5036 // Found an exit point in a function, e.g. return
5037 // (Note, there may be more than one return per function)
5039 pBranchLink(PCF(pc_fstart), PCF(pc));
5041 addSet(&pb->function_exits, pc);
5043 } else if(isCALL(pc)) {
5044 addSet(&pb->function_calls,pc);
5049 /* Re-allocate the registers so that there are no collisions
5050 * between local variables when one function call another */
5053 // pic14_deallocateAllRegs();
5055 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5062 /*-----------------------------------------------------------------*/
5063 /* AnalyzepCode - parse the pCode that has been generated and form */
5064 /* all of the logical connections. */
5066 /* Essentially what's done here is that the pCode flow is */
5068 /*-----------------------------------------------------------------*/
5070 void AnalyzepCode(char dbName)
5081 /* Phase 1 - Register allocation and peep hole optimization
5083 * The first part of the analysis is to determine the registers
5084 * that are used in the pCode. Once that is done, the peep rules
5085 * are applied to the code. We continue to loop until no more
5086 * peep rule optimizations are found (or until we exceed the
5087 * MAX_PASSES threshold).
5089 * When done, the required registers will be determined.
5095 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5096 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
5098 /* First, merge the labels with the instructions */
5099 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5100 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5102 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5103 //fprintf(stderr," analyze and merging block %c\n",dbName);
5104 pBlockMergeLabels(pb);
5107 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5111 changes = OptimizepCode(dbName);
5113 } while(changes && (i++ < MAX_PASSES));
5118 /*-----------------------------------------------------------------*/
5119 /* ispCodeFunction - returns true if *pc is the pCode of a */
5121 /*-----------------------------------------------------------------*/
5122 bool ispCodeFunction(pCode *pc)
5125 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5131 /*-----------------------------------------------------------------*/
5132 /* findFunction - Search for a function by name (given the name) */
5133 /* in the set of all functions that are in a pBlock */
5134 /* (note - I expect this to change because I'm planning to limit */
5135 /* pBlock's to just one function declaration */
5136 /*-----------------------------------------------------------------*/
5137 pCode *findFunction(char *fname)
5144 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5146 pc = setFirstItem(pb->function_entries);
5149 if((pc->type == PC_FUNCTION) &&
5151 (strcmp(fname, PCF(pc)->fname)==0))
5154 pc = setNextItem(pb->function_entries);
5162 void MarkUsedRegisters(set *regset)
5167 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5168 r2 = pic14_regWithIdx(r1->rIdx);
5174 void pBlockStats(FILE *of, pBlock *pb)
5180 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5182 // for now just print the first element of each set
5183 pc = setFirstItem(pb->function_entries);
5185 fprintf(of,";entry: ");
5188 pc = setFirstItem(pb->function_exits);
5190 fprintf(of,";has an exit\n");
5194 pc = setFirstItem(pb->function_calls);
5196 fprintf(of,";functions called:\n");
5199 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5200 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5202 pc = setNextItem(pb->function_calls);
5206 r = setFirstItem(pb->tregisters);
5208 int n = elementsInSet(pb->tregisters);
5210 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5213 fprintf(of,"; %s\n",r->name);
5214 r = setNextItem(pb->tregisters);
5219 /*-----------------------------------------------------------------*/
5220 /*-----------------------------------------------------------------*/
5222 static void sequencepCode(void)
5228 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5230 pb->seq = GpCodeSequenceNumber+1;
5232 for( pc = pb->pcHead; pc; pc = pc->next)
5233 pc->seq = ++GpCodeSequenceNumber;
5239 /*-----------------------------------------------------------------*/
5240 /*-----------------------------------------------------------------*/
5241 set *register_usage(pBlock *pb)
5244 set *registers=NULL;
5245 set *registersInCallPath = NULL;
5247 /* check recursion */
5249 pc = setFirstItem(pb->function_entries);
5256 if(pc->type != PC_FUNCTION)
5257 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5259 pc = setFirstItem(pb->function_calls);
5260 for( ; pc; pc = setNextItem(pb->function_calls)) {
5262 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5263 char *dest = get_op_from_instruction(PCI(pc));
5265 pcn = findFunction(dest);
5267 registersInCallPath = register_usage(pcn->pb);
5269 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5274 pBlockStats(stderr,pb); // debug
5277 // Mark the registers in this block as used.
5279 MarkUsedRegisters(pb->tregisters);
5280 if(registersInCallPath) {
5281 /* registers were used in the functions this pBlock has called */
5282 /* so now, we need to see if these collide with the ones we are */
5285 regs *r1,*r2, *newreg;
5287 DFPRINTF((stderr,"comparing registers\n"));
5289 r1 = setFirstItem(registersInCallPath);
5292 r2 = setFirstItem(pb->tregisters);
5294 while(r2 && (r1->type != REG_STK)) {
5296 if(r2->rIdx == r1->rIdx) {
5297 newreg = pic14_findFreeReg(REG_GPR);
5301 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5305 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5306 r1->rIdx, newreg->rIdx));
5307 r2->rIdx = newreg->rIdx;
5308 //if(r2->name) free(r2->name);
5310 r2->name = Safe_strdup(newreg->name);
5314 newreg->wasUsed = 1;
5316 r2 = setNextItem(pb->tregisters);
5319 r1 = setNextItem(registersInCallPath);
5322 /* Collisions have been resolved. Now free the registers in the call path */
5323 r1 = setFirstItem(registersInCallPath);
5325 if(r1->type != REG_STK) {
5326 newreg = pic14_regWithIdx(r1->rIdx);
5329 r1 = setNextItem(registersInCallPath);
5333 // MarkUsedRegisters(pb->registers);
5335 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5338 DFPRINTF((stderr,"returning regs\n"));
5340 DFPRINTF((stderr,"not returning regs\n"));
5342 DFPRINTF((stderr,"pBlock after register optim.\n"));
5343 pBlockStats(stderr,pb); // debug
5349 /*-----------------------------------------------------------------*/
5350 /* printCallTree - writes the call tree to a file */
5352 /*-----------------------------------------------------------------*/
5353 void pct2(FILE *of,pBlock *pb,int indent)
5357 // set *registersInCallPath = NULL;
5363 return; //recursion ?
5365 pc = setFirstItem(pb->function_entries);
5372 for(i=0;i<indent;i++) // Indentation
5375 if(pc->type == PC_FUNCTION)
5376 fprintf(of,"%s\n",PCF(pc)->fname);
5381 pc = setFirstItem(pb->function_calls);
5382 for( ; pc; pc = setNextItem(pb->function_calls)) {
5384 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5385 char *dest = get_op_from_instruction(PCI(pc));
5387 pcn = findFunction(dest);
5389 pct2(of,pcn->pb,indent+1);
5391 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5399 /*-----------------------------------------------------------------*/
5400 /* printCallTree - writes the call tree to a file */
5402 /*-----------------------------------------------------------------*/
5404 void printCallTree(FILE *of)
5416 fprintf(of, "\npBlock statistics\n");
5417 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5422 fprintf(of,"Call Tree\n");
5423 pbr = the_pFile->functions;
5427 if(!ispCodeFunction(pc))
5428 fprintf(of,"bug in call tree");
5431 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5433 while(pc->next && !ispCodeFunction(pc->next)) {
5435 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5436 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5444 fprintf(of,"\n**************\n\na better call tree\n");
5445 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5450 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5451 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5457 /*-----------------------------------------------------------------*/
5459 /*-----------------------------------------------------------------*/
5461 void InlineFunction(pBlock *pb)
5469 pc = setFirstItem(pb->function_calls);
5471 for( ; pc; pc = setNextItem(pb->function_calls)) {
5474 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5480 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5482 //fprintf(stderr,"Cool can inline:\n");
5483 //pcn->print(stderr,pcn);
5485 //fprintf(stderr,"recursive call Inline\n");
5486 InlineFunction(pcn->pb);
5487 //fprintf(stderr,"return from recursive call Inline\n");
5490 At this point, *pc points to a CALL mnemonic, and
5491 *pcn points to the function that is being called.
5493 To in-line this call, we need to remove the CALL
5494 and RETURN(s), and link the function pCode in with
5500 /* Remove the CALL */
5504 /* remove callee pBlock from the pBlock linked list */
5505 removepBlock(pcn->pb);
5513 /* Remove the Function pCode */
5514 pct = findNextInstruction(pcn->next);
5516 /* Link the function with the callee */
5517 pc->next = pcn->next;
5518 pcn->next->prev = pc;
5520 /* Convert the function name into a label */
5522 pbr = Safe_calloc(1,sizeof(pBranch));
5523 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5525 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5526 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5528 /* turn all of the return's except the last into goto's */
5529 /* check case for 2 instruction pBlocks */
5530 pce = findNextInstruction(pcn->next);
5532 pCode *pce_next = findNextInstruction(pce->next);
5534 if(pce_next == NULL) {
5535 /* found the last return */
5536 pCode *pc_call_next = findNextInstruction(pc_call->next);
5538 //fprintf(stderr,"found last return\n");
5539 //pce->print(stderr,pce);
5540 pce->prev->next = pc_call->next;
5541 pc_call->next->prev = pce->prev;
5542 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5552 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5558 /*-----------------------------------------------------------------*/
5560 /*-----------------------------------------------------------------*/
5562 void InlinepCode(void)
5571 if(!functionInlining)
5574 /* Loop through all of the function definitions and count the
5575 * number of times each one is called */
5576 //fprintf(stderr,"inlining %d\n",__LINE__);
5578 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5580 pc = setFirstItem(pb->function_calls);
5582 for( ; pc; pc = setNextItem(pb->function_calls)) {
5585 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5586 if(pcn && isPCF(pcn)) {
5587 PCF(pcn)->ncalled++;
5590 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5595 //fprintf(stderr,"inlining %d\n",__LINE__);
5597 /* Now, Loop through the function definitions again, but this
5598 * time inline those functions that have only been called once. */
5600 InlineFunction(the_pFile->pbHead);
5601 //fprintf(stderr,"inlining %d\n",__LINE__);
5603 for(pb = the_pFile->pbHead; pb; pb = pb->next)