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 int peepOptimizing = 1;
74 static int GpCodeSequenceNumber = 1;
75 static int GpcFlowSeq = 1;
77 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE))
78 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch)
79 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip)
80 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst)
81 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW))
82 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION))
83 #define isPCL(x) ((PCODE(x)->type == PC_LABEL))
84 #define isPCW(x) ((PCODE(x)->type == PC_WILD))
85 #define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE))
87 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL))
88 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
90 /****************************************************************/
91 /* Forward declarations */
92 /****************************************************************/
94 static void unlinkPC(pCode *pc);
96 static void genericAnalyze(pCode *pc);
97 static void AnalyzeGOTO(pCode *pc);
98 static void AnalyzeSKIP(pCode *pc);
99 static void AnalyzeRETURN(pCode *pc);
102 static void genericDestruct(pCode *pc);
103 static void genericPrint(FILE *of,pCode *pc);
105 static void pCodePrintLabel(FILE *of, pCode *pc);
106 static void pCodePrintFunction(FILE *of, pCode *pc);
107 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
108 static char *get_op_from_instruction( pCodeInstruction *pcc);
109 char *get_op( pCodeOp *pcop);
110 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
111 int pCodePeepMatchRule(pCode *pc);
112 void pBlockStats(FILE *of, pBlock *pb);
113 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
115 pCodeInstruction pciADDWF = {
116 {PC_OPCODE, NULL, NULL, 0, NULL,
129 1,0, // dest, bit instruction
132 (PCC_W | PCC_REGISTER), // inCond
133 (PCC_REGISTER | PCC_Z) // outCond
136 pCodeInstruction pciADDFW = {
137 {PC_OPCODE, NULL, NULL, 0, NULL,
150 0,0, // dest, bit instruction
153 (PCC_W | PCC_REGISTER), // inCond
154 (PCC_W | PCC_Z) // outCond
157 pCodeInstruction pciADDLW = {
158 {PC_OPCODE, NULL, NULL, 0, NULL,
171 0,0, // dest, bit instruction
175 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
178 pCodeInstruction pciANDLW = {
179 {PC_OPCODE, NULL, NULL, 0, NULL,
192 0,0, // dest, bit instruction
196 (PCC_W | PCC_Z) // outCond
199 pCodeInstruction pciANDWF = {
200 {PC_OPCODE, NULL, NULL, 0, NULL,
213 1,0, // dest, bit instruction
216 (PCC_W | PCC_REGISTER), // inCond
217 (PCC_REGISTER | PCC_Z) // outCond
220 pCodeInstruction pciANDFW = {
221 {PC_OPCODE, NULL, NULL, 0, NULL,
234 0,0, // dest, bit instruction
237 (PCC_W | PCC_REGISTER), // inCond
238 (PCC_W | PCC_Z) // outCond
241 pCodeInstruction pciBCF = {
242 {PC_OPCODE, NULL, NULL, 0, NULL,
255 1,1, // dest, bit instruction
258 PCC_REGISTER, // inCond
259 PCC_REGISTER // outCond
262 pCodeInstruction pciBSF = {
263 {PC_OPCODE, NULL, NULL, 0, NULL,
276 1,1, // dest, bit instruction
279 PCC_REGISTER, // inCond
280 PCC_REGISTER // outCond
283 pCodeInstruction pciBTFSC = {
284 {PC_OPCODE, NULL, NULL, 0, NULL,
297 0,1, // dest, bit instruction
300 PCC_REGISTER, // inCond
304 pCodeInstruction pciBTFSS = {
305 {PC_OPCODE, NULL, NULL, 0, NULL,
318 0,1, // dest, bit instruction
321 PCC_REGISTER, // inCond
325 pCodeInstruction pciCALL = {
326 {PC_OPCODE, NULL, NULL, 0, NULL,
339 0,0, // dest, bit instruction
346 pCodeInstruction pciCOMF = {
347 {PC_OPCODE, NULL, NULL, 0, NULL,
360 1,0, // dest, bit instruction
363 PCC_REGISTER, // inCond
364 PCC_REGISTER // outCond
367 pCodeInstruction pciCOMFW = {
368 {PC_OPCODE, NULL, NULL, 0, NULL,
381 0,0, // dest, bit instruction
384 PCC_REGISTER, // inCond
388 pCodeInstruction pciCLRF = {
389 {PC_OPCODE, NULL, NULL, 0, NULL,
402 0,0, // dest, bit instruction
405 PCC_REGISTER, // inCond
406 PCC_REGISTER // outCond
409 pCodeInstruction pciCLRW = {
410 {PC_OPCODE, NULL, NULL, 0, NULL,
423 0,0, // dest, bit instruction
430 pCodeInstruction pciDECF = {
431 {PC_OPCODE, NULL, NULL, 0, NULL,
444 1,0, // dest, bit instruction
447 PCC_REGISTER, // inCond
448 PCC_REGISTER // outCond
451 pCodeInstruction pciDECFW = {
452 {PC_OPCODE, NULL, NULL, 0, NULL,
465 0,0, // dest, bit instruction
468 PCC_REGISTER, // inCond
472 pCodeInstruction pciDECFSZ = {
473 {PC_OPCODE, NULL, NULL, 0, NULL,
486 1,0, // dest, bit instruction
489 PCC_REGISTER, // inCond
490 PCC_REGISTER // outCond
493 pCodeInstruction pciDECFSZW = {
494 {PC_OPCODE, NULL, NULL, 0, NULL,
507 0,0, // dest, bit instruction
510 PCC_REGISTER, // inCond
514 pCodeInstruction pciGOTO = {
515 {PC_OPCODE, NULL, NULL, 0, NULL,
528 0,0, // dest, bit instruction
535 pCodeInstruction pciINCF = {
536 {PC_OPCODE, NULL, NULL, 0, NULL,
549 1,0, // dest, bit instruction
552 PCC_REGISTER, // inCond
553 PCC_REGISTER // outCond
556 pCodeInstruction pciINCFW = {
557 {PC_OPCODE, NULL, NULL, 0, NULL,
570 0,0, // dest, bit instruction
573 PCC_REGISTER, // inCond
577 pCodeInstruction pciINCFSZ = {
578 {PC_OPCODE, NULL, NULL, 0, NULL,
591 1,0, // dest, bit instruction
594 PCC_REGISTER, // inCond
595 PCC_REGISTER // outCond
598 pCodeInstruction pciINCFSZW = {
599 {PC_OPCODE, NULL, NULL, 0, NULL,
612 0,0, // dest, bit instruction
615 PCC_REGISTER, // inCond
619 pCodeInstruction pciIORWF = {
620 {PC_OPCODE, NULL, NULL, 0, NULL,
633 1,0, // dest, bit instruction
636 (PCC_W | PCC_REGISTER), // inCond
637 (PCC_REGISTER | PCC_Z) // outCond
640 pCodeInstruction pciIORFW = {
641 {PC_OPCODE, NULL, NULL, 0, NULL,
654 0,0, // dest, bit instruction
657 (PCC_W | PCC_REGISTER), // inCond
658 (PCC_W | PCC_Z) // outCond
661 pCodeInstruction pciIORLW = {
662 {PC_OPCODE, NULL, NULL, 0, NULL,
675 0,0, // dest, bit instruction
679 (PCC_W | PCC_Z) // outCond
682 pCodeInstruction pciMOVF = {
683 {PC_OPCODE, NULL, NULL, 0, NULL,
696 1,0, // dest, bit instruction
699 PCC_REGISTER, // inCond
703 pCodeInstruction pciMOVFW = {
704 {PC_OPCODE, NULL, NULL, 0, NULL,
717 0,0, // dest, bit instruction
720 PCC_REGISTER, // inCond
721 (PCC_W | PCC_Z) // outCond
724 pCodeInstruction pciMOVWF = {
725 {PC_OPCODE, NULL, NULL, 0, NULL,
738 0,0, // dest, bit instruction
742 PCC_REGISTER // outCond
745 pCodeInstruction pciMOVLW = {
746 {PC_OPCODE, NULL, NULL, 0, NULL,
759 0,0, // dest, bit instruction
766 pCodeInstruction pciNOP = {
767 {PC_OPCODE, NULL, NULL, 0, NULL,
779 0,0, // dest, bit instruction
786 pCodeInstruction pciRETFIE = {
787 {PC_OPCODE, NULL, NULL, 0, NULL,
800 0,0, // dest, bit instruction
804 PCC_NONE // outCond (not true... affects the GIE bit too)
807 pCodeInstruction pciRETLW = {
808 {PC_OPCODE, NULL, NULL, 0, NULL,
821 0,0, // dest, bit instruction
828 pCodeInstruction pciRETURN = {
829 {PC_OPCODE, NULL, NULL, 0, NULL,
842 0,0, // dest, bit instruction
849 pCodeInstruction pciRLF = {
850 {PC_OPCODE, NULL, NULL, 0, NULL,
863 1,0, // dest, bit instruction
866 (PCC_C | PCC_REGISTER), // inCond
867 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
870 pCodeInstruction pciRLFW = {
871 {PC_OPCODE, NULL, NULL, 0, NULL,
884 0,0, // dest, bit instruction
887 (PCC_C | PCC_REGISTER), // inCond
888 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
891 pCodeInstruction pciRRF = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
905 1,0, // dest, bit instruction
908 (PCC_C | PCC_REGISTER), // inCond
909 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
912 pCodeInstruction pciRRFW = {
913 {PC_OPCODE, NULL, NULL, 0, NULL,
926 0,0, // dest, bit instruction
929 (PCC_C | PCC_REGISTER), // inCond
930 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
933 pCodeInstruction pciSUBWF = {
934 {PC_OPCODE, NULL, NULL, 0, NULL,
947 1,0, // dest, bit instruction
950 (PCC_W | PCC_REGISTER), // inCond
951 (PCC_REGISTER | PCC_Z) // outCond
954 pCodeInstruction pciSUBFW = {
955 {PC_OPCODE, NULL, NULL, 0, NULL,
968 0,0, // dest, bit instruction
971 (PCC_W | PCC_REGISTER), // inCond
972 (PCC_W | PCC_Z) // outCond
975 pCodeInstruction pciSUBLW = {
976 {PC_OPCODE, NULL, NULL, 0, NULL,
989 0,0, // dest, bit instruction
993 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
996 pCodeInstruction pciSWAPF = {
997 {PC_OPCODE, NULL, NULL, 0, NULL,
1003 NULL, // from branch
1010 1,0, // dest, bit instruction
1011 0,0, // branch, skip
1013 (PCC_REGISTER), // inCond
1014 (PCC_REGISTER) // outCond
1017 pCodeInstruction pciSWAPFW = {
1018 {PC_OPCODE, NULL, NULL, 0, NULL,
1024 NULL, // from branch
1031 0,0, // dest, bit instruction
1032 0,0, // branch, skip
1034 (PCC_REGISTER), // inCond
1038 pCodeInstruction pciTRIS = {
1039 {PC_OPCODE, NULL, NULL, 0, NULL,
1045 NULL, // from branch
1052 0,0, // dest, bit instruction
1053 0,0, // branch, skip
1056 PCC_REGISTER // outCond
1059 pCodeInstruction pciXORWF = {
1060 {PC_OPCODE, NULL, NULL, 0, NULL,
1066 NULL, // from branch
1073 1,0, // dest, bit instruction
1074 0,0, // branch, skip
1076 (PCC_W | PCC_REGISTER), // inCond
1077 (PCC_REGISTER | PCC_Z) // outCond
1080 pCodeInstruction pciXORFW = {
1081 {PC_OPCODE, NULL, NULL, 0, NULL,
1087 NULL, // from branch
1094 0,0, // dest, bit instruction
1095 0,0, // branch, skip
1097 (PCC_W | PCC_REGISTER), // inCond
1098 (PCC_W | PCC_Z) // outCond
1101 pCodeInstruction pciXORLW = {
1102 {PC_OPCODE, NULL, NULL, 0, NULL,
1108 NULL, // from branch
1115 0,0, // dest, bit instruction
1116 0,0, // branch, skip
1119 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1123 #define MAX_PIC14MNEMONICS 100
1124 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1126 /* This definition needs to be part of configure.in */
1127 // #define USE_VSNPRINTF
1129 #ifdef USE_VSNPRINTF
1130 // Alas, vsnprintf is not ANSI standard, and does not exist
1131 // on Solaris (and probably other non-Gnu flavored Unixes).
1133 /*-----------------------------------------------------------------*/
1134 /* SAFE_snprintf - like snprintf except the string pointer is */
1135 /* after the string has been printed to. This is */
1136 /* useful for printing to string as though if it */
1137 /* were a stream. */
1138 /*-----------------------------------------------------------------*/
1139 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1147 va_start(val, format);
1149 vsnprintf(*str, *size, format, val);
1155 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1163 #else // USE_VSNPRINTF
1165 // This version is *not* safe, despite the name.
1167 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1171 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1176 va_start(val, format);
1178 vsprintf(buffer, format, val);
1181 len = strlen(buffer);
1183 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1186 strcpy(*str, buffer);
1192 #endif // USE_VSNPRINTF
1195 extern void initStack(int base_address, int size);
1196 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1197 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1198 extern void init_pic(char *);
1200 void pCodeInitRegisters(void)
1203 initStack(0xfff, 8);
1204 init_pic(port->processor);
1206 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1207 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1208 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1209 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1210 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1211 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1213 pc_status.rIdx = IDX_STATUS;
1214 pc_fsr.rIdx = IDX_FSR;
1215 pc_indf.rIdx = IDX_INDF;
1216 pc_intcon.rIdx = IDX_INTCON;
1217 pc_pcl.rIdx = IDX_PCL;
1218 pc_pclath.rIdx = IDX_PCLATH;
1220 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1221 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1222 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1224 pc_kzero.rIdx = IDX_KZ;
1225 pc_wsave.rIdx = IDX_WSAVE;
1226 pc_ssave.rIdx = IDX_SSAVE;
1230 /*-----------------------------------------------------------------*/
1231 /* mnem2key - convert a pic mnemonic into a hash key */
1232 /* (BTW - this spreads the mnemonics quite well) */
1234 /*-----------------------------------------------------------------*/
1236 int mnem2key(char const *mnem)
1245 key += toupper(*mnem++) +1;
1249 return (key & 0x1f);
1253 void pic14initMnemonics(void)
1258 pCodeInstruction *pci;
1260 if(mnemonics_initialized)
1263 //FIXME - probably should NULL out the array before making the assignments
1264 //since we check the array contents below this initialization.
1266 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1267 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1268 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1269 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1270 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1271 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1272 pic14Mnemonics[POC_BCF] = &pciBCF;
1273 pic14Mnemonics[POC_BSF] = &pciBSF;
1274 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1275 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1276 pic14Mnemonics[POC_CALL] = &pciCALL;
1277 pic14Mnemonics[POC_COMF] = &pciCOMF;
1278 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1279 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1280 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1281 pic14Mnemonics[POC_DECF] = &pciDECF;
1282 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1283 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1284 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1285 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1286 pic14Mnemonics[POC_INCF] = &pciINCF;
1287 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1288 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1289 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1290 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1291 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1292 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1293 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1294 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1295 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1296 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1297 pic14Mnemonics[POC_NOP] = &pciNOP;
1298 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1299 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1300 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1301 pic14Mnemonics[POC_RLF] = &pciRLF;
1302 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1303 pic14Mnemonics[POC_RRF] = &pciRRF;
1304 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1305 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1306 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1307 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1308 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1309 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1310 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1311 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1312 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1313 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1315 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1316 if(pic14Mnemonics[i])
1317 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1318 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1321 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1322 pci = hTabNextItem(pic14MnemonicsHash, &key);
1325 mnemonics_initialized = 1;
1328 int getpCodePeepCommand(char *cmd);
1330 int getpCode(char *mnem,unsigned dest)
1333 pCodeInstruction *pci;
1334 int key = mnem2key(mnem);
1336 if(!mnemonics_initialized)
1337 pic14initMnemonics();
1339 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1343 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1344 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1348 pci = hTabNextItemWK (pic14MnemonicsHash);
1355 /*-----------------------------------------------------------------*
1356 * pic14initpCodePeepCommands
1358 *-----------------------------------------------------------------*/
1359 void pic14initpCodePeepCommands(void)
1367 hTabAddItem(&pic14pCodePeepCommandsHash,
1368 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1370 } while (peepCommands[i].cmd);
1372 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1375 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1376 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1381 /*-----------------------------------------------------------------
1384 *-----------------------------------------------------------------*/
1386 int getpCodePeepCommand(char *cmd)
1390 int key = mnem2key(cmd);
1393 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1396 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1397 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1401 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1408 char getpBlock_dbName(pBlock *pb)
1414 return pb->cmemmap->dbName;
1418 void pBlockConvert2ISR(pBlock *pb)
1429 /*-----------------------------------------------------------------*/
1430 /* movepBlock2Head - given the dbname of a pBlock, move all */
1431 /* instances to the front of the doubly linked */
1432 /* list of pBlocks */
1433 /*-----------------------------------------------------------------*/
1435 void movepBlock2Head(char dbName)
1439 pb = the_pFile->pbHead;
1443 if(getpBlock_dbName(pb) == dbName) {
1444 pBlock *pbn = pb->next;
1445 pb->next = the_pFile->pbHead;
1446 the_pFile->pbHead->prev = pb;
1447 the_pFile->pbHead = pb;
1450 pb->prev->next = pbn;
1452 // If the pBlock that we just moved was the last
1453 // one in the link of all of the pBlocks, then we
1454 // need to point the tail to the block just before
1455 // the one we moved.
1456 // Note: if pb->next is NULL, then pb must have
1457 // been the last pBlock in the chain.
1460 pbn->prev = pb->prev;
1462 the_pFile->pbTail = pb->prev;
1473 void copypCode(FILE *of, char dbName)
1477 if(!of || !the_pFile)
1480 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1481 if(getpBlock_dbName(pb) == dbName) {
1488 void pcode_test(void)
1491 DFPRINTF((stderr,"pcode is alive!\n"));
1501 /* create the file name */
1502 strcpy(buffer,srcFileName);
1503 strcat(buffer,".p");
1505 if( !(pFile = fopen(buffer, "w" ))) {
1506 werror(E_FILE_OPEN_ERR,buffer);
1510 fprintf(pFile,"pcode dump\n\n");
1512 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1513 fprintf(pFile,"\n\tNew pBlock\n\n");
1515 fprintf(pFile,"%s",pb->cmemmap->sname);
1517 fprintf(pFile,"internal pblock");
1519 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1520 printpBlock(pFile,pb);
1524 /*-----------------------------------------------------------------*/
1525 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1526 /* ister, RegCond will return the bit being referenced. */
1528 /* fixme - why not just OR in the pcop bit field */
1529 /*-----------------------------------------------------------------*/
1531 static int RegCond(pCodeOp *pcop)
1537 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1538 switch(PCORB(pcop)->bit) {
1552 /*-----------------------------------------------------------------*/
1553 /* newpCode - create and return a newly initialized pCode */
1555 /* fixme - rename this */
1557 /* The purpose of this routine is to create a new Instruction */
1558 /* pCode. This is called by gen.c while the assembly code is being */
1562 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1563 /* (note that the op is analogous to but not the */
1564 /* same thing as the opcode of the instruction.) */
1565 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1568 /* a pointer to the new malloc'd pCode is returned. */
1572 /*-----------------------------------------------------------------*/
1573 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1575 pCodeInstruction *pci ;
1577 if(!mnemonics_initialized)
1578 pic14initMnemonics();
1580 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1582 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1583 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1586 if(pci->inCond == PCC_EXAMINE_PCOP)
1587 pci->inCond = RegCond(pcop);
1589 if(pci->outCond == PCC_EXAMINE_PCOP)
1590 pci->outCond = RegCond(pcop);
1592 pci->pc.prev = pci->pc.next = NULL;
1593 return (pCode *)pci;
1596 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1602 /*-----------------------------------------------------------------*/
1603 /* newpCodeWild - create a "wild" as in wild card pCode */
1605 /* Wild pcodes are used during the peep hole optimizer to serve */
1606 /* as place holders for any instruction. When a snippet of code is */
1607 /* compared to a peep hole rule, the wild card opcode will match */
1608 /* any instruction. However, the optional operand and label are */
1609 /* additional qualifiers that must also be matched before the */
1610 /* line (of assembly code) is declared matched. Note that the */
1611 /* operand may be wild too. */
1613 /* Note, a wild instruction is specified just like a wild var: */
1614 /* %4 ; A wild instruction, */
1615 /* See the peeph.def file for additional examples */
1617 /*-----------------------------------------------------------------*/
1619 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1624 pcw = Safe_calloc(1,sizeof(pCodeWild));
1626 pcw->pci.pc.type = PC_WILD;
1627 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1628 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1629 pcw->pci.pc.pb = NULL;
1631 // pcw->pci.pc.analyze = genericAnalyze;
1632 pcw->pci.pc.destruct = genericDestruct;
1633 pcw->pci.pc.print = genericPrint;
1635 pcw->id = pCodeID; // this is the 'n' in %n
1636 pcw->operand = optional_operand;
1637 pcw->label = optional_label;
1639 pcw->mustBeBitSkipInst = 0;
1640 pcw->mustNotBeBitSkipInst = 0;
1641 pcw->invertBitSkipInst = 0;
1643 return ( (pCode *)pcw);
1647 /*-----------------------------------------------------------------*/
1648 /* newPcodeInlineP - create a new pCode from a char string */
1649 /*-----------------------------------------------------------------*/
1652 pCode *newpCodeInlineP(char *cP)
1657 pcc = Safe_calloc(1,sizeof(pCodeComment));
1659 pcc->pc.type = PC_INLINE;
1660 pcc->pc.prev = pcc->pc.next = NULL;
1661 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1664 // pcc->pc.analyze = genericAnalyze;
1665 pcc->pc.destruct = genericDestruct;
1666 pcc->pc.print = genericPrint;
1669 pcc->comment = Safe_strdup(cP);
1671 pcc->comment = NULL;
1673 return ( (pCode *)pcc);
1677 /*-----------------------------------------------------------------*/
1678 /* newPcodeCharP - create a new pCode from a char string */
1679 /*-----------------------------------------------------------------*/
1681 pCode *newpCodeCharP(char *cP)
1686 pcc = Safe_calloc(1,sizeof(pCodeComment));
1688 pcc->pc.type = PC_COMMENT;
1689 pcc->pc.prev = pcc->pc.next = NULL;
1690 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1693 // pcc->pc.analyze = genericAnalyze;
1694 pcc->pc.destruct = genericDestruct;
1695 pcc->pc.print = genericPrint;
1698 pcc->comment = Safe_strdup(cP);
1700 pcc->comment = NULL;
1702 return ( (pCode *)pcc);
1706 /*-----------------------------------------------------------------*/
1707 /* newpCodeFunction - */
1708 /*-----------------------------------------------------------------*/
1711 pCode *newpCodeFunction(char *mod,char *f)
1715 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1716 //_ALLOC(pcf,sizeof(pCodeFunction));
1718 pcf->pc.type = PC_FUNCTION;
1719 pcf->pc.prev = pcf->pc.next = NULL;
1720 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1723 // pcf->pc.analyze = genericAnalyze;
1724 pcf->pc.destruct = genericDestruct;
1725 pcf->pc.print = pCodePrintFunction;
1730 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1731 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1732 strcpy(pcf->modname,mod);
1734 pcf->modname = NULL;
1737 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1738 pcf->fname = Safe_calloc(1,strlen(f)+1);
1739 strcpy(pcf->fname,f);
1743 return ( (pCode *)pcf);
1747 /*-----------------------------------------------------------------*/
1749 /*-----------------------------------------------------------------*/
1751 void destructpCodeFlow(pCode *pc)
1753 if(!pc || !isPCFL(pc))
1757 free(PCFL(pc)->uses);
1765 pCode *newpCodeFlow(void )
1769 //_ALLOC(pcflow,sizeof(pCodeFlow));
1770 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1772 pcflow->pc.type = PC_FLOW;
1773 pcflow->pc.prev = pcflow->pc.next = NULL;
1774 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1775 pcflow->pc.pb = NULL;
1777 // pcflow->pc.analyze = genericAnalyze;
1778 pcflow->pc.destruct = destructpCodeFlow;
1779 pcflow->pc.print = genericPrint;
1781 pcflow->pc.seq = GpcFlowSeq++;
1784 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1786 pcflow->from = pcflow->to = NULL;
1788 pcflow->inCond = PCC_NONE;
1789 pcflow->outCond = PCC_NONE;
1792 return ( (pCode *)pcflow);
1796 /*-----------------------------------------------------------------*/
1797 /* newpCodeCSource - create a new pCode Source Symbol */
1798 /*-----------------------------------------------------------------*/
1800 pCode *newpCodeCSource(int ln, char *f, char *l)
1805 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1807 pccs->pc.type = PC_CSOURCE;
1808 pccs->pc.prev = pccs->pc.next = NULL;
1811 pccs->pc.destruct = genericDestruct;
1812 pccs->pc.print = genericPrint;
1814 pccs->line_number = ln;
1816 pccs->line = Safe_strdup(l);
1821 pccs->file_name = Safe_strdup(f);
1823 pccs->file_name = NULL;
1825 return ( (pCode *)pccs);
1828 /*-----------------------------------------------------------------*/
1829 /* pCodeLabelDestruct - free memory used by a label. */
1830 /*-----------------------------------------------------------------*/
1831 static void pCodeLabelDestruct(pCode *pc)
1837 if((pc->type == PC_LABEL) && PCL(pc)->label)
1838 free(PCL(pc)->label);
1844 pCode *newpCodeLabel(char *name, int key)
1850 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1852 pcl->pc.type = PC_LABEL;
1853 pcl->pc.prev = pcl->pc.next = NULL;
1854 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1857 // pcl->pc.analyze = genericAnalyze;
1858 pcl->pc.destruct = pCodeLabelDestruct;
1859 pcl->pc.print = pCodePrintLabel;
1865 sprintf(s,"_%05d_DS_",key);
1870 pcl->label = Safe_strdup(s);
1873 return ( (pCode *)pcl);
1878 /*-----------------------------------------------------------------*/
1879 /* newpBlock - create and return a pointer to a new pBlock */
1880 /*-----------------------------------------------------------------*/
1881 pBlock *newpBlock(void)
1886 PpB = Safe_calloc(1,sizeof(pBlock) );
1887 PpB->next = PpB->prev = NULL;
1889 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1890 PpB->tregisters = NULL;
1897 /*-----------------------------------------------------------------*/
1898 /* newpCodeChain - create a new chain of pCodes */
1899 /*-----------------------------------------------------------------*
1901 * This function will create a new pBlock and the pointer to the
1902 * pCode that is passed in will be the first pCode in the block.
1903 *-----------------------------------------------------------------*/
1906 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1909 pBlock *pB = newpBlock();
1911 pB->pcHead = pB->pcTail = pc;
1918 /*-----------------------------------------------------------------*/
1919 /* newpCodeOpLabel - Create a new label given the key */
1920 /* Note, a negative key means that the label is part of wild card */
1921 /* (and hence a wild card label) used in the pCodePeep */
1922 /* optimizations). */
1923 /*-----------------------------------------------------------------*/
1925 pCodeOp *newpCodeOpLabel(char *name, int key)
1928 static int label_key=-1;
1932 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1933 pcop->type = PO_LABEL;
1938 sprintf(s=buffer,"_%05d_DS_",key);
1940 s = name, key = label_key--;
1943 pcop->name = Safe_strdup(s);
1945 ((pCodeOpLabel *)pcop)->key = key;
1950 /*-----------------------------------------------------------------*/
1951 /*-----------------------------------------------------------------*/
1952 pCodeOp *newpCodeOpLit(int lit)
1958 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1959 pcop->type = PO_LITERAL;
1963 sprintf(s,"0x%02x",lit);
1965 pcop->name = Safe_strdup(s);
1968 ((pCodeOpLit *)pcop)->lit = lit;
1973 /*-----------------------------------------------------------------*/
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
1979 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1980 pcop->type = PO_IMMEDIATE;
1982 pcop->name = Safe_strdup(name);
1983 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
1989 PCOI(pcop)->index = index;
1990 PCOI(pcop)->offset = offset;
1991 PCOI(pcop)->_const = code_space;
1996 /*-----------------------------------------------------------------*/
1997 /*-----------------------------------------------------------------*/
1998 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2004 if(!pcwb || !subtype) {
2005 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2009 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2010 pcop->type = PO_WILD;
2011 sprintf(s,"%%%d",id);
2012 pcop->name = Safe_strdup(s);
2014 PCOW(pcop)->id = id;
2015 PCOW(pcop)->pcwb = pcwb;
2016 PCOW(pcop)->subtype = subtype;
2017 PCOW(pcop)->matched = NULL;
2022 /*-----------------------------------------------------------------*/
2023 /*-----------------------------------------------------------------*/
2024 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2028 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2029 pcop->type = PO_GPR_BIT;
2031 pcop->name = Safe_strdup(s);
2035 PCORB(pcop)->bit = bit;
2036 PCORB(pcop)->inBitSpace = inBitSpace;
2041 /*-----------------------------------------------------------------*
2042 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2044 * If rIdx >=0 then a specific register from the set of registers
2045 * will be selected. If rIdx <0, then a new register will be searched
2047 *-----------------------------------------------------------------*/
2049 pCodeOp *newpCodeOpReg(int rIdx)
2053 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2058 PCOR(pcop)->rIdx = rIdx;
2059 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2061 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2064 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2065 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2068 pcop->type = PCOR(pcop)->r->pc_type;
2073 pCodeOp *newpCodeOpRegFromStr(char *name)
2077 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2078 PCOR(pcop)->r = allocRegByName(name, 1);
2079 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2080 pcop->type = PCOR(pcop)->r->pc_type;
2081 pcop->name = PCOR(pcop)->r->name;
2086 /*-----------------------------------------------------------------*/
2087 /*-----------------------------------------------------------------*/
2089 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2096 pcop = newpCodeOpBit(name, -1,0);
2100 pcop = newpCodeOpLit(-1);
2104 pcop = newpCodeOpLabel(NULL,-1);
2107 pcop = newpCodeOpReg(-1);
2111 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2114 pcop->name = Safe_strdup(name);
2122 /*-----------------------------------------------------------------*/
2123 /*-----------------------------------------------------------------*/
2124 void pCodeConstString(char *name, char *value)
2128 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2133 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2137 sprintf(buffer,"; %s = %s",name,value);
2139 addpCode2pBlock(pb,newpCodeCharP(buffer));
2140 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2143 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2149 /*-----------------------------------------------------------------*/
2150 /*-----------------------------------------------------------------*/
2151 void pCodeReadCodeTable(void)
2155 fprintf(stderr, " %s\n",__FUNCTION__);
2157 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2161 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2162 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2163 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2164 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2166 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2167 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2168 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2169 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2174 /*-----------------------------------------------------------------*/
2175 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2176 /*-----------------------------------------------------------------*/
2177 void addpCode2pBlock(pBlock *pb, pCode *pc)
2180 /* If this is the first pcode to be added to a block that
2181 * was initialized with a NULL pcode, then go ahead and
2182 * make this pcode the head and tail */
2183 pb->pcHead = pb->pcTail = pc;
2185 pb->pcTail->next = pc;
2186 pc->prev = pb->pcTail;
2193 /*-----------------------------------------------------------------*/
2194 /* addpBlock - place a pBlock into the pFile */
2195 /*-----------------------------------------------------------------*/
2196 void addpBlock(pBlock *pb)
2198 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2201 /* First time called, we'll pass through here. */
2202 //_ALLOC(the_pFile,sizeof(pFile));
2203 the_pFile = Safe_calloc(1,sizeof(pFile));
2204 the_pFile->pbHead = the_pFile->pbTail = pb;
2205 the_pFile->functions = NULL;
2209 the_pFile->pbTail->next = pb;
2210 pb->prev = the_pFile->pbTail;
2212 the_pFile->pbTail = pb;
2215 /*-----------------------------------------------------------------*/
2216 /* removepBlock - remove a pBlock from the pFile */
2217 /*-----------------------------------------------------------------*/
2218 void removepBlock(pBlock *pb)
2226 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2228 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2231 if(pbs == the_pFile->pbHead)
2232 the_pFile->pbHead = pbs->next;
2234 if (pbs == the_pFile->pbTail)
2235 the_pFile->pbTail = pbs->prev;
2238 pbs->next->prev = pbs->prev;
2241 pbs->prev->next = pbs->next;
2248 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2252 /*-----------------------------------------------------------------*/
2253 /* printpCode - write the contents of a pCode to a file */
2254 /*-----------------------------------------------------------------*/
2255 void printpCode(FILE *of, pCode *pc)
2266 fprintf(of,"warning - unable to print pCode\n");
2269 /*-----------------------------------------------------------------*/
2270 /* printpBlock - write the contents of a pBlock to a file */
2271 /*-----------------------------------------------------------------*/
2272 void printpBlock(FILE *of, pBlock *pb)
2282 for(pc = pb->pcHead; pc; pc = pc->next)
2287 /*-----------------------------------------------------------------*/
2289 /* pCode processing */
2293 /*-----------------------------------------------------------------*/
2295 static void unlinkPC(pCode *pc)
2301 fprintf(stderr,"Unlinking: ");
2302 printpCode(stderr, pc);
2305 pc->prev->next = pc->next;
2307 pc->next->prev = pc->prev;
2309 pc->prev = pc->next = NULL;
2312 static void genericDestruct(pCode *pc)
2314 //fprintf(stderr,"warning, calling default pCode destructor\n");
2323 /*-----------------------------------------------------------------*/
2324 /*-----------------------------------------------------------------*/
2325 void pBlockRegs(FILE *of, pBlock *pb)
2330 r = setFirstItem(pb->tregisters);
2332 r = setNextItem(pb->tregisters);
2337 /*-----------------------------------------------------------------*/
2338 /*-----------------------------------------------------------------*/
2339 char *get_op(pCodeOp *pcop)
2342 static char buffer[50];
2348 switch(pcop->type) {
2351 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2352 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2354 return PCOR(pcop)->r->name;
2357 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2358 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2362 // return PCOR(pcc->pcop)->r)->name;
2365 size = sizeof(buffer);
2366 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2367 if(PCOI(pcop)->_const) {
2369 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2370 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2373 8 * PCOI(pcop)->offset );
2375 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2378 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2379 SAFE_snprintf(&s,&size,"(%s + %d)",
2381 PCOI(pcop)->index );
2383 SAFE_snprintf(&s,&size,"%s",pcop->name);
2390 size = sizeof(buffer);
2391 if( PCOR(pcop)->instance) {
2392 SAFE_snprintf(&s,&size,"(%s + %d)",
2394 PCOR(pcop)->instance );
2395 //fprintf(stderr,"PO_DIR %s\n",buffer);
2397 SAFE_snprintf(&s,&size,"%s",pcop->name);
2407 return "NO operand";
2411 /*-----------------------------------------------------------------*/
2412 /*-----------------------------------------------------------------*/
2413 static char *get_op_from_instruction( pCodeInstruction *pcc)
2417 return get_op(pcc->pcop);
2419 return ("ERROR Null: "__FUNCTION__);
2423 /*-----------------------------------------------------------------*/
2424 /*-----------------------------------------------------------------*/
2425 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2428 fprintf(of,"pcodeopprint- not implemented\n");
2431 /*-----------------------------------------------------------------*/
2432 /*-----------------------------------------------------------------*/
2433 char *pCode2str(char *str, int size, pCode *pc)
2441 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2443 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2445 if(PCI(pc)->isBitInst) {
2446 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2447 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2448 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2449 PCI(pc)->pcop->name ,
2450 PCI(pc)->pcop->name );
2452 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2453 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2454 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2455 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2457 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2458 //PCI(pc)->pcop->t.bit );
2461 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2462 if( PCI(pc)->num_ops == 2)
2463 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2465 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2468 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2470 if( PCI(pc)->num_ops == 2)
2471 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2479 /* assuming that comment ends with a \n */
2480 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2484 /* assuming that inline code ends with a \n */
2485 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2489 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2492 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2495 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2498 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2501 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2510 /*-----------------------------------------------------------------*/
2511 /* genericPrint - the contents of a pCode to a file */
2512 /*-----------------------------------------------------------------*/
2513 static void genericPrint(FILE *of, pCode *pc)
2521 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2525 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2529 // If the opcode has a label, print that first
2531 pBranch *pbl = PCI(pc)->label;
2532 while(pbl && pbl->pc) {
2533 if(pbl->pc->type == PC_LABEL)
2534 pCodePrintLabel(of, pbl->pc);
2540 genericPrint(of,PCODE(PCI(pc)->cline));
2545 pCode2str(str, 256, pc);
2547 fprintf(of,"%s",str);
2550 fprintf(of, "\t;key=%03x",pc->seq);
2552 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2556 pBranch *dpb = pc->to; // debug
2558 switch ( dpb->pc->type) {
2560 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2563 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2566 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2569 fprintf(of, "\t;flow");
2583 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2584 if(PCW(pc)->pci.label)
2585 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2587 if(PCW(pc)->operand) {
2588 fprintf(of,";\toperand ");
2589 pCodeOpPrint(of,PCW(pc)->operand );
2594 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2598 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2602 fprintf(of,"unknown pCode type %d\n",pc->type);
2607 /*-----------------------------------------------------------------*/
2608 /* pCodePrintFunction - prints function begin/end */
2609 /*-----------------------------------------------------------------*/
2611 static void pCodePrintFunction(FILE *of, pCode *pc)
2617 if( ((pCodeFunction *)pc)->modname)
2618 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2620 if(PCF(pc)->fname) {
2621 pBranch *exits = PCF(pc)->to;
2623 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2626 exits = exits->next;
2629 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2632 if((PCF(pc)->from &&
2633 PCF(pc)->from->pc->type == PC_FUNCTION &&
2634 PCF(PCF(pc)->from->pc)->fname) )
2635 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2637 fprintf(of,"; exit point [can't find entry point]\n");
2640 /*-----------------------------------------------------------------*/
2641 /* pCodePrintLabel - prints label */
2642 /*-----------------------------------------------------------------*/
2644 static void pCodePrintLabel(FILE *of, pCode *pc)
2651 fprintf(of,"%s\n",PCL(pc)->label);
2652 else if (PCL(pc)->key >=0)
2653 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2655 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2658 /*-----------------------------------------------------------------*/
2659 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2660 /* remove it if it is found. */
2661 /*-----------------------------------------------------------------*/
2662 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2669 if(pcl->type == PC_OPCODE)
2670 b = PCI(pcl)->label;
2672 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2677 //fprintf (stderr, "%s \n",__FUNCTION__);
2678 //pcl->print(stderr,pcl);
2679 //pc->print(stderr,pc);
2682 //fprintf (stderr, "found label\n");
2686 bprev->next = b->next; /* Not first pCode in chain */
2690 PCI(pcl)->label = b->next; /* First pCode in chain */
2693 return; /* A label can't occur more than once */
2701 /*-----------------------------------------------------------------*/
2702 /*-----------------------------------------------------------------*/
2703 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2719 /*-----------------------------------------------------------------*/
2720 /* pBranchLink - given two pcodes, this function will link them */
2721 /* together through their pBranches */
2722 /*-----------------------------------------------------------------*/
2723 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2727 // Declare a new branch object for the 'from' pCode.
2729 //_ALLOC(b,sizeof(pBranch));
2730 b = Safe_calloc(1,sizeof(pBranch));
2731 b->pc = PCODE(t); // The link to the 'to' pCode.
2734 f->to = pBranchAppend(f->to,b);
2736 // Now do the same for the 'to' pCode.
2738 //_ALLOC(b,sizeof(pBranch));
2739 b = Safe_calloc(1,sizeof(pBranch));
2743 t->from = pBranchAppend(t->from,b);
2748 /*-----------------------------------------------------------------*/
2749 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2751 /*-----------------------------------------------------------------*/
2752 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2765 /*-----------------------------------------------------------------*/
2766 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2767 /*-----------------------------------------------------------------*/
2768 static void pCodeUnlink(pCode *pc)
2773 if(!pc->prev || !pc->next) {
2774 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2778 /* first remove the pCode from the chain */
2779 pc->prev->next = pc->next;
2780 pc->next->prev = pc->prev;
2782 /* Now for the hard part... */
2784 /* Remove the branches */
2788 pc1 = pb1->pc; /* Get the pCode that branches to the
2789 * one we're unlinking */
2791 /* search for the link back to this pCode (the one we're
2793 if(pb2 = pBranchFind(pc1->to,pc)) {
2794 pb2->pc = pc->to->pc; // make the replacement
2796 /* if the pCode we're unlinking contains multiple 'to'
2797 * branches (e.g. this a skip instruction) then we need
2798 * to copy these extra branches to the chain. */
2800 pBranchAppend(pb2, pc->to->next);
2809 /*-----------------------------------------------------------------*/
2810 /*-----------------------------------------------------------------*/
2812 static void genericAnalyze(pCode *pc)
2822 // Go through the pCodes that are in pCode chain and link
2823 // them together through the pBranches. Note, the pCodes
2824 // are linked together as a contiguous stream like the
2825 // assembly source code lines. The linking here mimics this
2826 // except that comments are not linked in.
2828 pCode *npc = pc->next;
2830 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2831 pBranchLink(pc,npc);
2836 /* reached the end of the pcode chain without finding
2837 * an instruction we could link to. */
2841 fprintf(stderr,"analyze PC_FLOW\n");
2848 /*-----------------------------------------------------------------*/
2849 /*-----------------------------------------------------------------*/
2850 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2854 if(pc->type == PC_LABEL) {
2855 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2858 if(pc->type == PC_OPCODE) {
2859 pbr = PCI(pc)->label;
2861 if(pbr->pc->type == PC_LABEL) {
2862 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2872 /*-----------------------------------------------------------------*/
2873 /*-----------------------------------------------------------------*/
2874 int checkLabel(pCode *pc)
2878 if(pc && isPCI(pc)) {
2879 pbr = PCI(pc)->label;
2881 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2891 /*-----------------------------------------------------------------*/
2892 /* findLabel - Search the pCode for a particular label */
2893 /*-----------------------------------------------------------------*/
2894 pCode * findLabel(pCodeOpLabel *pcop_label)
2902 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2903 for(pc = pb->pcHead; pc; pc = pc->next)
2904 if(compareLabel(pc,pcop_label))
2909 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2913 /*-----------------------------------------------------------------*/
2914 /* findNextpCode - given a pCode, find the next of type 'pct' */
2915 /* in the linked list */
2916 /*-----------------------------------------------------------------*/
2917 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2930 /*-----------------------------------------------------------------*/
2931 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2932 /* in the linked list */
2933 /*-----------------------------------------------------------------*/
2934 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2946 /*-----------------------------------------------------------------*/
2947 /* findNextInstruction - given a pCode, find the next instruction */
2948 /* in the linked list */
2949 /*-----------------------------------------------------------------*/
2950 pCode * findNextInstruction(pCode *pci)
2955 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2959 fprintf(stderr,"findNextInstruction: ");
2960 printpCode(stderr, pc);
2965 //fprintf(stderr,"Couldn't find instruction\n");
2969 /*-----------------------------------------------------------------*/
2970 /* findNextInstruction - given a pCode, find the next instruction */
2971 /* in the linked list */
2972 /*-----------------------------------------------------------------*/
2973 pCode * findPrevInstruction(pCode *pci)
2975 return findPrevpCode(pci, PC_OPCODE);
2978 /*-----------------------------------------------------------------*/
2979 /* findFunctionEnd - given a pCode find the end of the function */
2980 /* that contains it */
2981 /*-----------------------------------------------------------------*/
2982 pCode * findFunctionEnd(pCode *pc)
2986 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2992 fprintf(stderr,"Couldn't find function end\n");
2997 /*-----------------------------------------------------------------*/
2998 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2999 /* instruction with which it is associated. */
3000 /*-----------------------------------------------------------------*/
3001 static void AnalyzeLabel(pCode *pc)
3010 static void AnalyzeGOTO(pCode *pc)
3013 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3017 static void AnalyzeSKIP(pCode *pc)
3020 pBranchLink(pc,findNextInstruction(pc->next));
3021 pBranchLink(pc,findNextInstruction(pc->next->next));
3025 static void AnalyzeRETURN(pCode *pc)
3028 // branch_link(pc,findFunctionEnd(pc->next));
3034 /*-----------------------------------------------------------------*/
3035 /*-----------------------------------------------------------------*/
3036 regs * getRegFromInstruction(pCode *pc)
3041 PCI(pc)->num_ops == 0 )
3044 switch(PCI(pc)->pcop->type) {
3047 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3051 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3052 return PCOR(PCI(pc)->pcop)->r;
3055 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3056 return NULL; // PCOR(PCI(pc)->pcop)->r;
3059 return PCOR(PCI(pc)->pcop)->r;
3062 //fprintf(stderr, "getRegFromInstruction - dir\n");
3063 return PCOR(PCI(pc)->pcop)->r;
3065 //fprintf(stderr, "getRegFromInstruction - literal\n");
3069 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3070 //genericPrint(stderr, pc);
3078 /*-----------------------------------------------------------------*/
3079 /*-----------------------------------------------------------------*/
3081 void AnalyzepBlock(pBlock *pb)
3088 /* Find all of the registers used in this pBlock
3089 * by looking at each instruction and examining it's
3092 for(pc = pb->pcHead; pc; pc = pc->next) {
3094 /* Is this an instruction with operands? */
3095 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3097 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3099 /* Loop through all of the registers declared so far in
3100 this block and see if we find this one there */
3102 regs *r = setFirstItem(pb->tregisters);
3105 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3106 PCOR(PCI(pc)->pcop)->r = r;
3109 r = setNextItem(pb->tregisters);
3113 /* register wasn't found */
3114 r = Safe_calloc(1, sizeof(regs));
3115 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3116 addSet(&pb->tregisters, r);
3117 PCOR(PCI(pc)->pcop)->r = r;
3118 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3120 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3123 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3124 if(PCOR(PCI(pc)->pcop)->r) {
3125 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3126 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3128 if(PCI(pc)->pcop->name)
3129 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3131 fprintf(stderr,"ERROR: NULL register\n");
3140 /*-----------------------------------------------------------------*/
3142 /*-----------------------------------------------------------------*/
3143 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3145 void InsertpFlow(pCode *pc, pCode **pflow)
3147 PCFL(*pflow)->end = pc;
3149 if(!pc || !pc->next)
3152 *pflow = newpCodeFlow();
3153 pCodeInsertAfter(pc, *pflow);
3156 /*-----------------------------------------------------------------*/
3157 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3158 /* the flow blocks. */
3160 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3161 * point the instruction flow changes.
3163 /*-----------------------------------------------------------------*/
3164 void BuildFlow(pBlock *pb)
3167 pCode *last_pci=NULL;
3174 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3175 /* Insert a pCodeFlow object at the beginning of a pBlock */
3177 pflow = newpCodeFlow(); /* Create a new Flow object */
3178 pflow->next = pb->pcHead; /* Make the current head the next object */
3179 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3180 pb->pcHead = pflow; /* Make the Flow object the head */
3183 for( pc = findNextInstruction(pb->pcHead);
3184 (pc=findNextInstruction(pc)) != NULL; ) {
3187 PCI(pc)->pcflow = PCFL(pflow);
3189 if( PCI(pc)->isSkip) {
3191 /* The two instructions immediately following this one
3192 * mark the beginning of a new flow segment */
3194 while(pc && PCI(pc)->isSkip) {
3196 PCI(pc)->pcflow = PCFL(pflow);
3200 InsertpFlow(pc, &pflow);
3201 pc=findNextInstruction(pc->next);
3209 PCI(pc)->pcflow = PCFL(pflow);
3211 InsertpFlow(pc, &pflow);
3213 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3215 InsertpFlow(pc, &pflow);
3218 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3220 /* This instruction marks the beginning of a
3221 * new flow segment */
3225 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3227 PCI(pc)->pcflow = PCFL(pflow);
3234 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3235 PCFL(pflow)->end = pb->pcTail;
3238 /*-------------------------------------------------------------------*/
3239 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3240 /* the flow blocks. */
3242 * unBuildFlow removes pCodeFlow objects from a pCode chain
3244 /*-----------------------------------------------------------------*/
3245 void unBuildFlow(pBlock *pb)
3254 pCode *pcn = pc->next;
3258 PCI(pc)->pcflow = NULL;
3260 } else if(isPCFL(pc)) {
3270 /*-----------------------------------------------------------------*/
3271 /*-----------------------------------------------------------------*/
3272 void dumpCond(int cond)
3275 static char *pcc_str[] = {
3289 int ncond = sizeof(pcc_str) / sizeof(char *);
3292 fprintf(stderr, "0x%04X\n",cond);
3294 for(i=0,j=1; i<ncond; i++, j<<=1)
3296 fprintf(stderr, " %s\n",pcc_str[i]);
3300 /*-----------------------------------------------------------------*/
3301 /*-----------------------------------------------------------------*/
3302 void FlowStats(pCodeFlow *pcflow)
3310 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3312 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3315 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3320 fprintf(stderr, " FlowStats inCond: ");
3321 dumpCond(pcflow->inCond);
3322 fprintf(stderr, " FlowStats outCond: ");
3323 dumpCond(pcflow->outCond);
3327 /*-----------------------------------------------------------------*/
3328 /*-----------------------------------------------------------------*/
3329 void FillFlow(pCodeFlow *pcflow)
3338 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3340 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3343 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3354 int inCond = PCI(pc)->inCond;
3355 int outCond = PCI(pc)->outCond;
3357 if( (reg = getRegFromInstruction(pc)) != NULL) {
3358 if(isSTATUS_REG(reg)) {
3360 //fprintf(stderr, " FillFlow - Status register\n");
3361 //pc->print(stderr,pc);
3362 /* Check to see if the register banks are changing */
3363 if(PCI(pc)->isModReg) {
3365 pCodeOp *pcop = PCI(pc)->pcop;
3366 switch(PCI(pc)->op) {
3369 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3370 fprintf(stderr, " FillFlow - Set RP0\n");
3371 //outCond |= PCC_REG_BANK1;
3372 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3373 //fprintf(stderr, " FillFlow - Set RP1\n");
3374 //outCond |= PCC_REG_BANK3;
3378 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3379 fprintf(stderr, " FillFlow - Clr RP0\n");
3380 //outCond |= PCC_REG_BANK1;
3381 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3382 fprintf(stderr, " FillFlow - Clr RP1\n");
3383 //outCond |= PCC_REG_BANK3;
3387 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3388 genericPrint(stderr, pc);
3393 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3396 pcflow->inCond |= (inCond & ~pcflow->outCond);
3397 pcflow->outCond |= outCond;
3401 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3405 fprintf(stderr, " FillFlow - Bad end of flow\n");
3407 fprintf(stderr, " FillFlow - Ending flow with\n ");
3408 pc->print(stderr,pc);
3411 fprintf(stderr, " FillFlow inCond: ");
3412 dumpCond(pcflow->inCond);
3413 fprintf(stderr, " FillFlow outCond: ");
3414 dumpCond(pcflow->outCond);
3418 /*-----------------------------------------------------------------*/
3419 /*-----------------------------------------------------------------*/
3420 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3423 if(!from || !to || !to->pcflow || !from->pcflow)
3426 addSet(&(from->pcflow->to), to->pcflow);
3427 addSet(&(to->pcflow->from), from->pcflow);
3431 /*-----------------------------------------------------------------*/
3432 /*-----------------------------------------------------------------*/
3433 void LinkFlow(pBlock *pb)
3439 //fprintf(stderr,"linkflow \n");
3440 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3441 (pcflow = findNextpCode(pcflow->next, PC_FLOW)) != NULL;) {
3444 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3446 //FillFlow(PCFL(pcflow));
3448 pc = PCFL(pcflow)->end;
3450 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3451 if(isPCI_SKIP(pc)) {
3452 //fprintf(stderr, "ends with skip\n");
3453 pct=findNextInstruction(pc->next);
3454 LinkFlow_pCode(PCI(pc),PCI(pct));
3455 pct=findNextInstruction(pct->next);
3456 LinkFlow_pCode(PCI(pc),PCI(pct));
3460 //if(isPCI_BRANCH(pc)) {
3461 //fprintf(stderr, "ends with branch\n");
3467 fprintf(stderr, "ends with non-branching instruction:\n");
3468 //pc->print(stderr,pc);
3471 fprintf(stderr, "has no end pcode\n");
3476 /*-----------------------------------------------------------------*/
3477 /*-----------------------------------------------------------------*/
3478 int OptimizepBlock(pBlock *pb)
3483 if(!pb || !peepOptimizing)
3486 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3488 for(pc = pb->pcHead; pc; pc = pc->next)
3489 matches += pCodePeepMatchRule(pc);
3492 pc = findNextInstruction(pb->pcHead);
3497 if(pCodePeepMatchRule(pc)) {
3502 pc = findNextInstruction(pcprev->next);
3504 pc = findNextInstruction(pb->pcHead);
3506 pc = findNextInstruction(pc->next);
3510 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3515 /*-----------------------------------------------------------------*/
3516 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3517 /*-----------------------------------------------------------------*/
3518 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3522 for(pc = pcs; pc; pc = pc->next) {
3524 if((pc->type == PC_OPCODE) &&
3526 (PCI(pc)->pcop->type == PO_LABEL) &&
3527 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3535 /*-----------------------------------------------------------------*/
3536 /*-----------------------------------------------------------------*/
3537 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
3542 (PCI(pc)->pcop->type == PO_LABEL)) {
3544 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3546 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
3548 free(pcol->pcop.name);
3550 sprintf(buffer,"_%05d_DS_",pcl->key);
3552 pcol->pcop.name = Safe_strdup(buffer);
3553 pcol->key = pcl->key;
3554 //pc->print(stderr,pc);
3561 /*-----------------------------------------------------------------*/
3562 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3563 /* pCode chain if they're not used. */
3564 /*-----------------------------------------------------------------*/
3565 void pBlockRemoveUnusedLabels(pBlock *pb)
3567 pCode *pc; pCodeLabel *pcl;
3572 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
3574 pBranch *pbr = PCI(pc)->label;
3575 if(pbr && pbr->next) {
3576 pCode *pcd = pb->pcHead;
3578 //fprintf(stderr, "multiple labels\n");
3579 //pc->print(stderr,pc);
3584 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
3585 //fprintf(stderr,"Used by:\n");
3586 //pcd->print(stderr,pcd);
3588 exchangeLabels(PCL(pbr->pc),pcd);
3597 for(pc = pb->pcHead; pc; pc = pc->next) {
3599 if(isPCL(pc)) // pc->type == PC_LABEL)
3601 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
3602 pcl = PCL(PCI(pc)->label->pc);
3605 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
3607 /* This pCode is a label, so search the pBlock to see if anyone
3610 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3611 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
3612 /* Couldn't find an instruction that refers to this label
3613 * So, unlink the pCode label from it's pCode chain
3614 * and destroy the label */
3615 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
3617 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
3618 if(pc->type == PC_LABEL) {
3620 pCodeLabelDestruct(pc);
3622 unlinkpCodeFromBranch(pc, PCODE(pcl));
3623 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3634 /*-----------------------------------------------------------------*/
3635 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3636 /* chain and put them into pBranches that are */
3637 /* associated with the appropriate pCode */
3639 /*-----------------------------------------------------------------*/
3640 void pBlockMergeLabels(pBlock *pb)
3643 pCode *pc, *pcnext=NULL;
3648 /* First, Try to remove any unused labels */
3649 //pBlockRemoveUnusedLabels(pb);
3651 /* Now loop through the pBlock and merge the labels with the opcodes */
3653 for(pc = pb->pcHead; pc; pc = pc->next) {
3655 if(pc->type == PC_LABEL) {
3657 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
3658 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3659 if((pcnext = findNextInstruction(pc) )) {
3661 pCode *pcn = pc->next;
3663 // Unlink the pCode label from it's pCode chain
3666 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3667 // And link it into the instruction's pBranch labels. (Note, since
3668 // it's possible to have multiple labels associated with one instruction
3669 // we must provide a means to accomodate the additional labels. Thus
3670 // the labels are placed into the singly-linked list "label" as
3671 // opposed to being a single member of the pCodeInstruction.)
3673 //_ALLOC(pbr,sizeof(pBranch));
3674 pbr = Safe_calloc(1,sizeof(pBranch));
3679 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3684 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
3686 } else if(pc->type == PC_CSOURCE) {
3688 /* merge the source line symbolic info into the next instruction */
3689 if((pcnext = findNextInstruction(pc) )) {
3691 pCode *pcn = pc->next;
3693 // Unlink the pCode label from it's pCode chain
3695 PCI(pcnext)->cline = PCCS(pc);
3696 //fprintf(stderr, "merging CSRC\n");
3697 //genericPrint(stderr,pcnext);
3704 pBlockRemoveUnusedLabels(pb);
3708 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3710 int OptimizepCode(char dbName)
3712 #define MAX_PASSES 4
3721 DFPRINTF((stderr," Optimizing pCode\n"));
3725 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3726 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3727 matches += OptimizepBlock(pb);
3730 while(matches && ++passes < MAX_PASSES);
3735 /*-----------------------------------------------------------------*/
3736 /* popCopyGPR2Bit - copy a pcode operator */
3737 /*-----------------------------------------------------------------*/
3739 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3743 pcop = newpCodeOpBit(pc->name, bitval, 0);
3745 if( !( (pcop->type == PO_LABEL) ||
3746 (pcop->type == PO_LITERAL) ||
3747 (pcop->type == PO_STR) ))
3748 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3756 /*-----------------------------------------------------------------*/
3757 /*-----------------------------------------------------------------*/
3758 int InstructionRegBank(pCode *pc)
3762 if( (reg = getRegFromInstruction(pc)) == NULL)
3765 return REG_BANK(reg);
3770 /*-----------------------------------------------------------------*/
3771 /*-----------------------------------------------------------------*/
3772 void FixRegisterBanking(pBlock *pb)
3784 pc = findNextpCode(pb->pcHead, PC_FLOW);
3787 /* loop through all of the flow blocks with in one pblock */
3789 //fprintf(stderr,"Register banking\n");
3792 /* at this point, pc should point to a PC_FLOW object */
3795 /* for each flow block, determine the register banking
3800 //genericPrint(stderr, pc);
3802 reg = getRegFromInstruction(pc);
3805 fprintf(stderr, " %s ",reg->name);
3806 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3810 if(reg && REG_BANK(reg)!=cur_bank) {
3811 /* Examine the instruction before this one to make sure it is
3812 * not a skip type instruction */
3813 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3814 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3815 int b = cur_bank ^ REG_BANK(reg);
3817 //fprintf(stderr, "Cool! can switch banks\n");
3818 cur_bank = REG_BANK(reg);
3820 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3821 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3822 pCodeInsertAfter(pc->prev, new_pc);
3823 if(PCI(pc)->label) {
3824 PCI(new_pc)->label = PCI(pc)->label;
3825 PCI(pc)->label = NULL;
3828 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3829 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3830 pCodeInsertAfter(pc, new_pc);
3836 //fprintf(stderr, "Bummer can't switch banks\n");
3844 } while(pc && !(isPCFL(pc)));
3846 if(pcprev && cur_bank) {
3847 /* Brute force - make sure that we point to bank 0 at the
3848 * end of each flow block */
3849 new_pc = newpCode(POC_BCF,
3850 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3851 pCodeInsertAfter(pcprev, new_pc);
3859 void pBlockDestruct(pBlock *pb)
3870 /*-----------------------------------------------------------------*/
3871 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3872 /* name dbName and combine them */
3873 /* into one block */
3874 /*-----------------------------------------------------------------*/
3875 void mergepBlocks(char dbName)
3878 pBlock *pb, *pbmerged = NULL,*pbn;
3880 pb = the_pFile->pbHead;
3882 //fprintf(stderr," merging blocks named %c\n",dbName);
3886 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3887 if( getpBlock_dbName(pb) == dbName) {
3889 //fprintf(stderr," merged block %c\n",dbName);
3894 addpCode2pBlock(pbmerged, pb->pcHead);
3895 /* addpCode2pBlock doesn't handle the tail: */
3896 pbmerged->pcTail = pb->pcTail;
3898 pb->prev->next = pbn;
3900 pbn->prev = pb->prev;
3905 //printpBlock(stderr, pbmerged);
3912 /*-----------------------------------------------------------------*/
3913 /* AnalyzeBanking - Called after the memory addresses have been */
3914 /* assigned to the registers. */
3916 /*-----------------------------------------------------------------*/
3917 void AnalyzeBanking(void)
3926 /* Phase 2 - Flow Analysis
3928 * In this phase, the pCode is partition into pCodeFlow
3929 * blocks. The flow blocks mark the points where a continuous
3930 * stream of instructions changes flow (e.g. because of
3931 * a call or goto or whatever).
3934 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3937 /* Phase 2 - Flow Analysis - linking flow blocks
3939 * In this phase, the individual flow blocks are examined
3940 * to determine their order of excution.
3943 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3946 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3947 FixRegisterBanking(pb);
3950 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3952 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3953 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3954 pcflow = pcflow->next) {
3956 FillFlow(PCFL(pcflow));
3960 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3962 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3963 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3964 pcflow = pcflow->next) {
3966 FlowStats(PCFL(pcflow));
3972 /*-----------------------------------------------------------------*/
3973 /* buildCallTree - look at the flow and extract all of the calls */
3975 /*-----------------------------------------------------------------*/
3976 set *register_usage(pBlock *pb);
3978 void buildCallTree(void )
3989 /* Now build the call tree.
3990 First we examine all of the pCodes for functions.
3991 Keep in mind that the function boundaries coincide
3992 with pBlock boundaries.
3994 The algorithm goes something like this:
3995 We have two nested loops. The outer loop iterates
3996 through all of the pBlocks/functions. The inner
3997 loop iterates through all of the pCodes for
3998 a given pBlock. When we begin iterating through
3999 a pBlock, the variable pc_fstart, pCode of the start
4000 of a function, is cleared. We then search for pCodes
4001 of type PC_FUNCTION. When one is encountered, we
4002 initialize pc_fstart to this and at the same time
4003 associate a new pBranch object that signifies a
4004 branch entry. If a return is found, then this signifies
4005 a function exit point. We'll link the pCodes of these
4006 returns to the matching pc_fstart.
4008 When we're done, a doubly linked list of pBranches
4009 will exist. The head of this list is stored in
4010 `the_pFile', which is the meta structure for all
4011 of the pCode. Look at the printCallTree function
4012 on how the pBranches are linked together.
4015 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4016 pCode *pc_fstart=NULL;
4017 for(pc = pb->pcHead; pc; pc = pc->next) {
4019 if (PCF(pc)->fname) {
4021 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4022 //fprintf(stderr," found main \n");
4023 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4027 pbr = Safe_calloc(1,sizeof(pBranch));
4028 pbr->pc = pc_fstart = pc;
4031 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4033 // Here's a better way of doing the same:
4034 addSet(&pb->function_entries, pc);
4037 // Found an exit point in a function, e.g. return
4038 // (Note, there may be more than one return per function)
4040 pBranchLink(PCF(pc_fstart), PCF(pc));
4042 addSet(&pb->function_exits, pc);
4044 } else if(isCALL(pc)) {
4045 addSet(&pb->function_calls,pc);
4050 /* Re-allocate the registers so that there are no collisions
4051 * between local variables when one function call another */
4053 pic14_deallocateAllRegs();
4055 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4062 /*-----------------------------------------------------------------*/
4063 /* AnalyzepCode - parse the pCode that has been generated and form */
4064 /* all of the logical connections. */
4066 /* Essentially what's done here is that the pCode flow is */
4068 /*-----------------------------------------------------------------*/
4070 void AnalyzepCode(char dbName)
4081 /* Phase 1 - Register allocation and peep hole optimization
4083 * The first part of the analysis is to determine the registers
4084 * that are used in the pCode. Once that is done, the peep rules
4085 * are applied to the code. We continue to loop until no more
4086 * peep rule optimizations are found (or until we exceed the
4087 * MAX_PASSES threshold).
4089 * When done, the required registers will be determined.
4095 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4096 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4098 /* First, merge the labels with the instructions */
4099 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4100 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4102 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4103 //fprintf(stderr," analyze and merging block %c\n",dbName);
4104 pBlockMergeLabels(pb);
4107 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4111 changes = OptimizepCode(dbName);
4113 } while(changes && (i++ < MAX_PASSES));
4118 /*-----------------------------------------------------------------*/
4119 /* ispCodeFunction - returns true if *pc is the pCode of a */
4121 /*-----------------------------------------------------------------*/
4122 bool ispCodeFunction(pCode *pc)
4125 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4131 /*-----------------------------------------------------------------*/
4132 /* findFunction - Search for a function by name (given the name) */
4133 /* in the set of all functions that are in a pBlock */
4134 /* (note - I expect this to change because I'm planning to limit */
4135 /* pBlock's to just one function declaration */
4136 /*-----------------------------------------------------------------*/
4137 pCode *findFunction(char *fname)
4144 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4146 pc = setFirstItem(pb->function_entries);
4149 if((pc->type == PC_FUNCTION) &&
4151 (strcmp(fname, PCF(pc)->fname)==0))
4154 pc = setNextItem(pb->function_entries);
4162 void MarkUsedRegisters(set *regset)
4167 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4168 r2 = pic14_regWithIdx(r1->rIdx);
4174 void pBlockStats(FILE *of, pBlock *pb)
4180 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4182 // for now just print the first element of each set
4183 pc = setFirstItem(pb->function_entries);
4185 fprintf(of,";entry: ");
4188 pc = setFirstItem(pb->function_exits);
4190 fprintf(of,";has an exit\n");
4194 pc = setFirstItem(pb->function_calls);
4196 fprintf(of,";functions called:\n");
4199 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4200 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4202 pc = setNextItem(pb->function_calls);
4206 r = setFirstItem(pb->tregisters);
4208 int n = elementsInSet(pb->tregisters);
4210 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4213 fprintf(of,"; %s\n",r->name);
4214 r = setNextItem(pb->tregisters);
4219 /*-----------------------------------------------------------------*/
4220 /*-----------------------------------------------------------------*/
4221 static void sequencepCode(void)
4227 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4229 pb->seq = GpCodeSequenceNumber+1;
4231 for( pc = pb->pcHead; pc; pc = pc->next)
4232 pc->seq = ++GpCodeSequenceNumber;
4237 /*-----------------------------------------------------------------*/
4238 /*-----------------------------------------------------------------*/
4239 set *register_usage(pBlock *pb)
4242 set *registers=NULL;
4243 set *registersInCallPath = NULL;
4245 /* check recursion */
4247 pc = setFirstItem(pb->function_entries);
4254 if(pc->type != PC_FUNCTION)
4255 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4257 pc = setFirstItem(pb->function_calls);
4258 for( ; pc; pc = setNextItem(pb->function_calls)) {
4260 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4261 char *dest = get_op_from_instruction(PCI(pc));
4263 pcn = findFunction(dest);
4265 registersInCallPath = register_usage(pcn->pb);
4267 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4272 pBlockStats(stderr,pb); // debug
4275 // Mark the registers in this block as used.
4277 MarkUsedRegisters(pb->tregisters);
4278 if(registersInCallPath) {
4279 /* registers were used in the functions this pBlock has called */
4280 /* so now, we need to see if these collide with the ones we are */
4283 regs *r1,*r2, *newreg;
4285 DFPRINTF((stderr,"comparing registers\n"));
4287 r1 = setFirstItem(registersInCallPath);
4290 r2 = setFirstItem(pb->tregisters);
4292 while(r2 && (r1->type != REG_STK)) {
4294 if(r2->rIdx == r1->rIdx) {
4295 newreg = pic14_findFreeReg(REG_GPR);
4299 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4303 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4304 r1->rIdx, newreg->rIdx));
4305 r2->rIdx = newreg->rIdx;
4306 //if(r2->name) free(r2->name);
4308 r2->name = Safe_strdup(newreg->name);
4312 newreg->wasUsed = 1;
4314 r2 = setNextItem(pb->tregisters);
4317 r1 = setNextItem(registersInCallPath);
4320 /* Collisions have been resolved. Now free the registers in the call path */
4321 r1 = setFirstItem(registersInCallPath);
4323 if(r1->type != REG_STK) {
4324 newreg = pic14_regWithIdx(r1->rIdx);
4327 r1 = setNextItem(registersInCallPath);
4331 // MarkUsedRegisters(pb->registers);
4333 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4336 DFPRINTF((stderr,"returning regs\n"));
4338 DFPRINTF((stderr,"not returning regs\n"));
4340 DFPRINTF((stderr,"pBlock after register optim.\n"));
4341 pBlockStats(stderr,pb); // debug
4347 /*-----------------------------------------------------------------*/
4348 /* printCallTree - writes the call tree to a file */
4350 /*-----------------------------------------------------------------*/
4351 void pct2(FILE *of,pBlock *pb,int indent)
4355 // set *registersInCallPath = NULL;
4361 return; //recursion ?
4363 pc = setFirstItem(pb->function_entries);
4370 for(i=0;i<indent;i++) // Indentation
4373 if(pc->type == PC_FUNCTION)
4374 fprintf(of,"%s\n",PCF(pc)->fname);
4379 pc = setFirstItem(pb->function_calls);
4380 for( ; pc; pc = setNextItem(pb->function_calls)) {
4382 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4383 char *dest = get_op_from_instruction(PCI(pc));
4385 pcn = findFunction(dest);
4387 pct2(of,pcn->pb,indent+1);
4389 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4397 /*-----------------------------------------------------------------*/
4398 /* printCallTree - writes the call tree to a file */
4400 /*-----------------------------------------------------------------*/
4402 void printCallTree(FILE *of)
4414 fprintf(of, "\npBlock statistics\n");
4415 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4420 fprintf(of,"Call Tree\n");
4421 pbr = the_pFile->functions;
4425 if(!ispCodeFunction(pc))
4426 fprintf(of,"bug in call tree");
4429 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4431 while(pc->next && !ispCodeFunction(pc->next)) {
4433 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4434 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
4442 fprintf(of,"\n**************\n\na better call tree\n");
4443 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4448 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4449 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
4455 /*-----------------------------------------------------------------*/
4457 /*-----------------------------------------------------------------*/
4459 void InlineFunction(pBlock *pb)
4467 pc = setFirstItem(pb->function_calls);
4469 for( ; pc; pc = setNextItem(pb->function_calls)) {
4472 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
4478 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
4480 //fprintf(stderr,"Cool can inline:\n");
4481 //pcn->print(stderr,pcn);
4483 //fprintf(stderr,"recursive call Inline\n");
4484 InlineFunction(pcn->pb);
4485 //fprintf(stderr,"return from recursive call Inline\n");
4488 At this point, *pc points to a CALL mnemonic, and
4489 *pcn points to the function that is being called.
4491 To in-line this call, we need to remove the CALL
4492 and RETURN(s), and link the function pCode in with
4498 /* Remove the CALL */
4502 /* remove callee pBlock from the pBlock linked list */
4503 removepBlock(pcn->pb);
4511 /* Remove the Function pCode */
4512 pct = findNextInstruction(pcn->next);
4514 /* Link the function with the callee */
4515 pc->next = pcn->next;
4516 pcn->next->prev = pc;
4518 /* Convert the function name into a label */
4520 pbr = Safe_calloc(1,sizeof(pBranch));
4521 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
4523 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
4524 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
4526 /* turn all of the return's except the last into goto's */
4527 /* check case for 2 instruction pBlocks */
4528 pce = findNextInstruction(pcn->next);
4530 pCode *pce_next = findNextInstruction(pce->next);
4532 if(pce_next == NULL) {
4533 /* found the last return */
4534 pCode *pc_call_next = findNextInstruction(pc_call->next);
4536 //fprintf(stderr,"found last return\n");
4537 //pce->print(stderr,pce);
4538 pce->prev->next = pc_call->next;
4539 pc_call->next->prev = pce->prev;
4540 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
4550 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4556 /*-----------------------------------------------------------------*/
4558 /*-----------------------------------------------------------------*/
4560 void InlinepCode(void)
4570 /* Loop through all of the function definitions and count the
4571 * number of times each one is called */
4572 //fprintf(stderr,"inlining %d\n",__LINE__);
4574 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4576 pc = setFirstItem(pb->function_calls);
4578 for( ; pc; pc = setNextItem(pb->function_calls)) {
4581 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
4582 if(pcn && isPCF(pcn)) {
4583 PCF(pcn)->ncalled++;
4586 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4591 //fprintf(stderr,"inlining %d\n",__LINE__);
4593 /* Now, Loop through the function definitions again, but this
4594 * time inline those functions that have only been called once. */
4596 InlineFunction(the_pFile->pbHead);
4597 //fprintf(stderr,"inlining %d\n",__LINE__);
4599 for(pb = the_pFile->pbHead; pb; pb = pb->next)