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 #define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL)
92 /****************************************************************/
93 /* Forward declarations */
94 /****************************************************************/
96 static void unlinkPC(pCode *pc);
98 static void genericAnalyze(pCode *pc);
99 static void AnalyzeGOTO(pCode *pc);
100 static void AnalyzeSKIP(pCode *pc);
101 static void AnalyzeRETURN(pCode *pc);
104 static void genericDestruct(pCode *pc);
105 static void genericPrint(FILE *of,pCode *pc);
107 static void pCodePrintLabel(FILE *of, pCode *pc);
108 static void pCodePrintFunction(FILE *of, pCode *pc);
109 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
110 static char *get_op_from_instruction( pCodeInstruction *pcc);
111 char *get_op( pCodeOp *pcop);
112 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
113 int pCodePeepMatchRule(pCode *pc);
114 void pBlockStats(FILE *of, pBlock *pb);
115 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
116 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
117 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
119 pCodeInstruction pciADDWF = {
120 {PC_OPCODE, NULL, NULL, 0, NULL,
133 1,0, // dest, bit instruction
136 (PCC_W | PCC_REGISTER), // inCond
137 (PCC_REGISTER | PCC_Z) // outCond
140 pCodeInstruction pciADDFW = {
141 {PC_OPCODE, NULL, NULL, 0, NULL,
154 0,0, // dest, bit instruction
157 (PCC_W | PCC_REGISTER), // inCond
158 (PCC_W | PCC_Z) // outCond
161 pCodeInstruction pciADDLW = {
162 {PC_OPCODE, NULL, NULL, 0, NULL,
175 0,0, // dest, bit instruction
179 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
182 pCodeInstruction pciANDLW = {
183 {PC_OPCODE, NULL, NULL, 0, NULL,
196 0,0, // dest, bit instruction
200 (PCC_W | PCC_Z) // outCond
203 pCodeInstruction pciANDWF = {
204 {PC_OPCODE, NULL, NULL, 0, NULL,
217 1,0, // dest, bit instruction
220 (PCC_W | PCC_REGISTER), // inCond
221 (PCC_REGISTER | PCC_Z) // outCond
224 pCodeInstruction pciANDFW = {
225 {PC_OPCODE, NULL, NULL, 0, NULL,
238 0,0, // dest, bit instruction
241 (PCC_W | PCC_REGISTER), // inCond
242 (PCC_W | PCC_Z) // outCond
245 pCodeInstruction pciBCF = {
246 {PC_OPCODE, NULL, NULL, 0, NULL,
259 1,1, // dest, bit instruction
262 PCC_REGISTER, // inCond
263 PCC_REGISTER // outCond
266 pCodeInstruction pciBSF = {
267 {PC_OPCODE, NULL, NULL, 0, NULL,
280 1,1, // dest, bit instruction
283 PCC_REGISTER, // inCond
284 PCC_REGISTER // outCond
287 pCodeInstruction pciBTFSC = {
288 {PC_OPCODE, NULL, NULL, 0, NULL,
301 0,1, // dest, bit instruction
304 PCC_REGISTER, // inCond
308 pCodeInstruction pciBTFSS = {
309 {PC_OPCODE, NULL, NULL, 0, NULL,
322 0,1, // dest, bit instruction
325 PCC_REGISTER, // inCond
329 pCodeInstruction pciCALL = {
330 {PC_OPCODE, NULL, NULL, 0, NULL,
343 0,0, // dest, bit instruction
350 pCodeInstruction pciCOMF = {
351 {PC_OPCODE, NULL, NULL, 0, NULL,
364 1,0, // dest, bit instruction
367 PCC_REGISTER, // inCond
368 PCC_REGISTER // outCond
371 pCodeInstruction pciCOMFW = {
372 {PC_OPCODE, NULL, NULL, 0, NULL,
385 0,0, // dest, bit instruction
388 PCC_REGISTER, // inCond
392 pCodeInstruction pciCLRF = {
393 {PC_OPCODE, NULL, NULL, 0, NULL,
406 0,0, // dest, bit instruction
409 PCC_REGISTER, // inCond
410 PCC_REGISTER // outCond
413 pCodeInstruction pciCLRW = {
414 {PC_OPCODE, NULL, NULL, 0, NULL,
427 0,0, // dest, bit instruction
434 pCodeInstruction pciDECF = {
435 {PC_OPCODE, NULL, NULL, 0, NULL,
448 1,0, // dest, bit instruction
451 PCC_REGISTER, // inCond
452 PCC_REGISTER // outCond
455 pCodeInstruction pciDECFW = {
456 {PC_OPCODE, NULL, NULL, 0, NULL,
469 0,0, // dest, bit instruction
472 PCC_REGISTER, // inCond
476 pCodeInstruction pciDECFSZ = {
477 {PC_OPCODE, NULL, NULL, 0, NULL,
490 1,0, // dest, bit instruction
493 PCC_REGISTER, // inCond
494 PCC_REGISTER // outCond
497 pCodeInstruction pciDECFSZW = {
498 {PC_OPCODE, NULL, NULL, 0, NULL,
511 0,0, // dest, bit instruction
514 PCC_REGISTER, // inCond
518 pCodeInstruction pciGOTO = {
519 {PC_OPCODE, NULL, NULL, 0, NULL,
532 0,0, // dest, bit instruction
539 pCodeInstruction pciINCF = {
540 {PC_OPCODE, NULL, NULL, 0, NULL,
553 1,0, // dest, bit instruction
556 PCC_REGISTER, // inCond
557 PCC_REGISTER // outCond
560 pCodeInstruction pciINCFW = {
561 {PC_OPCODE, NULL, NULL, 0, NULL,
574 0,0, // dest, bit instruction
577 PCC_REGISTER, // inCond
581 pCodeInstruction pciINCFSZ = {
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 1,0, // dest, bit instruction
598 PCC_REGISTER, // inCond
599 PCC_REGISTER // outCond
602 pCodeInstruction pciINCFSZW = {
603 {PC_OPCODE, NULL, NULL, 0, NULL,
616 0,0, // dest, bit instruction
619 PCC_REGISTER, // inCond
623 pCodeInstruction pciIORWF = {
624 {PC_OPCODE, NULL, NULL, 0, NULL,
637 1,0, // dest, bit instruction
640 (PCC_W | PCC_REGISTER), // inCond
641 (PCC_REGISTER | PCC_Z) // outCond
644 pCodeInstruction pciIORFW = {
645 {PC_OPCODE, NULL, NULL, 0, NULL,
658 0,0, // dest, bit instruction
661 (PCC_W | PCC_REGISTER), // inCond
662 (PCC_W | PCC_Z) // outCond
665 pCodeInstruction pciIORLW = {
666 {PC_OPCODE, NULL, NULL, 0, NULL,
679 0,0, // dest, bit instruction
683 (PCC_W | PCC_Z) // outCond
686 pCodeInstruction pciMOVF = {
687 {PC_OPCODE, NULL, NULL, 0, NULL,
700 1,0, // dest, bit instruction
703 PCC_REGISTER, // inCond
707 pCodeInstruction pciMOVFW = {
708 {PC_OPCODE, NULL, NULL, 0, NULL,
721 0,0, // dest, bit instruction
724 PCC_REGISTER, // inCond
725 (PCC_W | PCC_Z) // outCond
728 pCodeInstruction pciMOVWF = {
729 {PC_OPCODE, NULL, NULL, 0, NULL,
742 0,0, // dest, bit instruction
746 PCC_REGISTER // outCond
749 pCodeInstruction pciMOVLW = {
750 {PC_OPCODE, NULL, NULL, 0, NULL,
763 0,0, // dest, bit instruction
770 pCodeInstruction pciNOP = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
783 0,0, // dest, bit instruction
790 pCodeInstruction pciRETFIE = {
791 {PC_OPCODE, NULL, NULL, 0, NULL,
804 0,0, // dest, bit instruction
808 PCC_NONE // outCond (not true... affects the GIE bit too)
811 pCodeInstruction pciRETLW = {
812 {PC_OPCODE, NULL, NULL, 0, NULL,
825 0,0, // dest, bit instruction
832 pCodeInstruction pciRETURN = {
833 {PC_OPCODE, NULL, NULL, 0, NULL,
846 0,0, // dest, bit instruction
853 pCodeInstruction pciRLF = {
854 {PC_OPCODE, NULL, NULL, 0, NULL,
867 1,0, // dest, bit instruction
870 (PCC_C | PCC_REGISTER), // inCond
871 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
874 pCodeInstruction pciRLFW = {
875 {PC_OPCODE, NULL, NULL, 0, NULL,
888 0,0, // dest, bit instruction
891 (PCC_C | PCC_REGISTER), // inCond
892 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
895 pCodeInstruction pciRRF = {
896 {PC_OPCODE, NULL, NULL, 0, NULL,
909 1,0, // dest, bit instruction
912 (PCC_C | PCC_REGISTER), // inCond
913 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
916 pCodeInstruction pciRRFW = {
917 {PC_OPCODE, NULL, NULL, 0, NULL,
930 0,0, // dest, bit instruction
933 (PCC_C | PCC_REGISTER), // inCond
934 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
937 pCodeInstruction pciSUBWF = {
938 {PC_OPCODE, NULL, NULL, 0, NULL,
951 1,0, // dest, bit instruction
954 (PCC_W | PCC_REGISTER), // inCond
955 (PCC_REGISTER | PCC_Z) // outCond
958 pCodeInstruction pciSUBFW = {
959 {PC_OPCODE, NULL, NULL, 0, NULL,
972 0,0, // dest, bit instruction
975 (PCC_W | PCC_REGISTER), // inCond
976 (PCC_W | PCC_Z) // outCond
979 pCodeInstruction pciSUBLW = {
980 {PC_OPCODE, NULL, NULL, 0, NULL,
993 0,0, // dest, bit instruction
997 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1000 pCodeInstruction pciSWAPF = {
1001 {PC_OPCODE, NULL, NULL, 0, NULL,
1007 NULL, // from branch
1014 1,0, // dest, bit instruction
1015 0,0, // branch, skip
1017 (PCC_REGISTER), // inCond
1018 (PCC_REGISTER) // outCond
1021 pCodeInstruction pciSWAPFW = {
1022 {PC_OPCODE, NULL, NULL, 0, NULL,
1028 NULL, // from branch
1035 0,0, // dest, bit instruction
1036 0,0, // branch, skip
1038 (PCC_REGISTER), // inCond
1042 pCodeInstruction pciTRIS = {
1043 {PC_OPCODE, NULL, NULL, 0, NULL,
1049 NULL, // from branch
1056 0,0, // dest, bit instruction
1057 0,0, // branch, skip
1060 PCC_REGISTER // outCond
1063 pCodeInstruction pciXORWF = {
1064 {PC_OPCODE, NULL, NULL, 0, NULL,
1070 NULL, // from branch
1077 1,0, // dest, bit instruction
1078 0,0, // branch, skip
1080 (PCC_W | PCC_REGISTER), // inCond
1081 (PCC_REGISTER | PCC_Z) // outCond
1084 pCodeInstruction pciXORFW = {
1085 {PC_OPCODE, NULL, NULL, 0, NULL,
1091 NULL, // from branch
1098 0,0, // dest, bit instruction
1099 0,0, // branch, skip
1101 (PCC_W | PCC_REGISTER), // inCond
1102 (PCC_W | PCC_Z) // outCond
1105 pCodeInstruction pciXORLW = {
1106 {PC_OPCODE, NULL, NULL, 0, NULL,
1112 NULL, // from branch
1119 0,0, // dest, bit instruction
1120 0,0, // branch, skip
1123 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1127 #define MAX_PIC14MNEMONICS 100
1128 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1130 /* This definition needs to be part of configure.in */
1131 // #define USE_VSNPRINTF
1133 #ifdef USE_VSNPRINTF
1134 // Alas, vsnprintf is not ANSI standard, and does not exist
1135 // on Solaris (and probably other non-Gnu flavored Unixes).
1137 /*-----------------------------------------------------------------*/
1138 /* SAFE_snprintf - like snprintf except the string pointer is */
1139 /* after the string has been printed to. This is */
1140 /* useful for printing to string as though if it */
1141 /* were a stream. */
1142 /*-----------------------------------------------------------------*/
1143 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1151 va_start(val, format);
1153 vsnprintf(*str, *size, format, val);
1159 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1167 #else // USE_VSNPRINTF
1169 // This version is *not* safe, despite the name.
1171 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1175 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1180 va_start(val, format);
1182 vsprintf(buffer, format, val);
1185 len = strlen(buffer);
1187 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1190 strcpy(*str, buffer);
1196 #endif // USE_VSNPRINTF
1199 extern void initStack(int base_address, int size);
1200 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1201 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1202 extern void init_pic(char *);
1204 void pCodeInitRegisters(void)
1207 initStack(0xfff, 8);
1208 init_pic(port->processor);
1210 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1211 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1212 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1213 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1214 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1215 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1217 pc_status.rIdx = IDX_STATUS;
1218 pc_fsr.rIdx = IDX_FSR;
1219 pc_indf.rIdx = IDX_INDF;
1220 pc_intcon.rIdx = IDX_INTCON;
1221 pc_pcl.rIdx = IDX_PCL;
1222 pc_pclath.rIdx = IDX_PCLATH;
1224 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1225 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1226 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1228 pc_kzero.rIdx = IDX_KZ;
1229 pc_wsave.rIdx = IDX_WSAVE;
1230 pc_ssave.rIdx = IDX_SSAVE;
1234 /*-----------------------------------------------------------------*/
1235 /* mnem2key - convert a pic mnemonic into a hash key */
1236 /* (BTW - this spreads the mnemonics quite well) */
1238 /*-----------------------------------------------------------------*/
1240 int mnem2key(char const *mnem)
1249 key += toupper(*mnem++) +1;
1253 return (key & 0x1f);
1257 void pic14initMnemonics(void)
1262 pCodeInstruction *pci;
1264 if(mnemonics_initialized)
1267 //FIXME - probably should NULL out the array before making the assignments
1268 //since we check the array contents below this initialization.
1270 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1271 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1272 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1273 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1274 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1275 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1276 pic14Mnemonics[POC_BCF] = &pciBCF;
1277 pic14Mnemonics[POC_BSF] = &pciBSF;
1278 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1279 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1280 pic14Mnemonics[POC_CALL] = &pciCALL;
1281 pic14Mnemonics[POC_COMF] = &pciCOMF;
1282 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1283 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1284 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1285 pic14Mnemonics[POC_DECF] = &pciDECF;
1286 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1287 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1288 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1289 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1290 pic14Mnemonics[POC_INCF] = &pciINCF;
1291 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1292 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1293 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1294 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1295 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1296 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1297 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1298 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1299 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1300 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1301 pic14Mnemonics[POC_NOP] = &pciNOP;
1302 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1303 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1304 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1305 pic14Mnemonics[POC_RLF] = &pciRLF;
1306 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1307 pic14Mnemonics[POC_RRF] = &pciRRF;
1308 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1309 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1310 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1311 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1312 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1313 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1314 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1315 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1316 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1317 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1319 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1320 if(pic14Mnemonics[i])
1321 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1322 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1325 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1326 pci = hTabNextItem(pic14MnemonicsHash, &key);
1329 mnemonics_initialized = 1;
1332 int getpCodePeepCommand(char *cmd);
1334 int getpCode(char *mnem,unsigned dest)
1337 pCodeInstruction *pci;
1338 int key = mnem2key(mnem);
1340 if(!mnemonics_initialized)
1341 pic14initMnemonics();
1343 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1347 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1348 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1352 pci = hTabNextItemWK (pic14MnemonicsHash);
1359 /*-----------------------------------------------------------------*
1360 * pic14initpCodePeepCommands
1362 *-----------------------------------------------------------------*/
1363 void pic14initpCodePeepCommands(void)
1371 hTabAddItem(&pic14pCodePeepCommandsHash,
1372 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1374 } while (peepCommands[i].cmd);
1376 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1379 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1380 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1385 /*-----------------------------------------------------------------
1388 *-----------------------------------------------------------------*/
1390 int getpCodePeepCommand(char *cmd)
1394 int key = mnem2key(cmd);
1397 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1400 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1401 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1405 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1412 char getpBlock_dbName(pBlock *pb)
1418 return pb->cmemmap->dbName;
1422 void pBlockConvert2ISR(pBlock *pb)
1433 /*-----------------------------------------------------------------*/
1434 /* movepBlock2Head - given the dbname of a pBlock, move all */
1435 /* instances to the front of the doubly linked */
1436 /* list of pBlocks */
1437 /*-----------------------------------------------------------------*/
1439 void movepBlock2Head(char dbName)
1443 pb = the_pFile->pbHead;
1447 if(getpBlock_dbName(pb) == dbName) {
1448 pBlock *pbn = pb->next;
1449 pb->next = the_pFile->pbHead;
1450 the_pFile->pbHead->prev = pb;
1451 the_pFile->pbHead = pb;
1454 pb->prev->next = pbn;
1456 // If the pBlock that we just moved was the last
1457 // one in the link of all of the pBlocks, then we
1458 // need to point the tail to the block just before
1459 // the one we moved.
1460 // Note: if pb->next is NULL, then pb must have
1461 // been the last pBlock in the chain.
1464 pbn->prev = pb->prev;
1466 the_pFile->pbTail = pb->prev;
1477 void copypCode(FILE *of, char dbName)
1481 if(!of || !the_pFile)
1484 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1485 if(getpBlock_dbName(pb) == dbName) {
1492 void pcode_test(void)
1495 DFPRINTF((stderr,"pcode is alive!\n"));
1505 /* create the file name */
1506 strcpy(buffer,srcFileName);
1507 strcat(buffer,".p");
1509 if( !(pFile = fopen(buffer, "w" ))) {
1510 werror(E_FILE_OPEN_ERR,buffer);
1514 fprintf(pFile,"pcode dump\n\n");
1516 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1517 fprintf(pFile,"\n\tNew pBlock\n\n");
1519 fprintf(pFile,"%s",pb->cmemmap->sname);
1521 fprintf(pFile,"internal pblock");
1523 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1524 printpBlock(pFile,pb);
1528 /*-----------------------------------------------------------------*/
1529 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1530 /* ister, RegCond will return the bit being referenced. */
1532 /* fixme - why not just OR in the pcop bit field */
1533 /*-----------------------------------------------------------------*/
1535 static int RegCond(pCodeOp *pcop)
1541 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1542 switch(PCORB(pcop)->bit) {
1556 /*-----------------------------------------------------------------*/
1557 /* newpCode - create and return a newly initialized pCode */
1559 /* fixme - rename this */
1561 /* The purpose of this routine is to create a new Instruction */
1562 /* pCode. This is called by gen.c while the assembly code is being */
1566 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1567 /* (note that the op is analogous to but not the */
1568 /* same thing as the opcode of the instruction.) */
1569 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1572 /* a pointer to the new malloc'd pCode is returned. */
1576 /*-----------------------------------------------------------------*/
1577 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1579 pCodeInstruction *pci ;
1581 if(!mnemonics_initialized)
1582 pic14initMnemonics();
1584 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1586 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1587 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1590 if(pci->inCond == PCC_EXAMINE_PCOP)
1591 pci->inCond = RegCond(pcop);
1593 if(pci->outCond == PCC_EXAMINE_PCOP)
1594 pci->outCond = RegCond(pcop);
1596 pci->pc.prev = pci->pc.next = NULL;
1597 return (pCode *)pci;
1600 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1606 /*-----------------------------------------------------------------*/
1607 /* newpCodeWild - create a "wild" as in wild card pCode */
1609 /* Wild pcodes are used during the peep hole optimizer to serve */
1610 /* as place holders for any instruction. When a snippet of code is */
1611 /* compared to a peep hole rule, the wild card opcode will match */
1612 /* any instruction. However, the optional operand and label are */
1613 /* additional qualifiers that must also be matched before the */
1614 /* line (of assembly code) is declared matched. Note that the */
1615 /* operand may be wild too. */
1617 /* Note, a wild instruction is specified just like a wild var: */
1618 /* %4 ; A wild instruction, */
1619 /* See the peeph.def file for additional examples */
1621 /*-----------------------------------------------------------------*/
1623 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1628 pcw = Safe_calloc(1,sizeof(pCodeWild));
1630 pcw->pci.pc.type = PC_WILD;
1631 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1632 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1633 pcw->pci.pc.pb = NULL;
1635 // pcw->pci.pc.analyze = genericAnalyze;
1636 pcw->pci.pc.destruct = genericDestruct;
1637 pcw->pci.pc.print = genericPrint;
1639 pcw->id = pCodeID; // this is the 'n' in %n
1640 pcw->operand = optional_operand;
1641 pcw->label = optional_label;
1643 pcw->mustBeBitSkipInst = 0;
1644 pcw->mustNotBeBitSkipInst = 0;
1645 pcw->invertBitSkipInst = 0;
1647 return ( (pCode *)pcw);
1651 /*-----------------------------------------------------------------*/
1652 /* newPcodeInlineP - create a new pCode from a char string */
1653 /*-----------------------------------------------------------------*/
1656 pCode *newpCodeInlineP(char *cP)
1661 pcc = Safe_calloc(1,sizeof(pCodeComment));
1663 pcc->pc.type = PC_INLINE;
1664 pcc->pc.prev = pcc->pc.next = NULL;
1665 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1668 // pcc->pc.analyze = genericAnalyze;
1669 pcc->pc.destruct = genericDestruct;
1670 pcc->pc.print = genericPrint;
1673 pcc->comment = Safe_strdup(cP);
1675 pcc->comment = NULL;
1677 return ( (pCode *)pcc);
1681 /*-----------------------------------------------------------------*/
1682 /* newPcodeCharP - create a new pCode from a char string */
1683 /*-----------------------------------------------------------------*/
1685 pCode *newpCodeCharP(char *cP)
1690 pcc = Safe_calloc(1,sizeof(pCodeComment));
1692 pcc->pc.type = PC_COMMENT;
1693 pcc->pc.prev = pcc->pc.next = NULL;
1694 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1697 // pcc->pc.analyze = genericAnalyze;
1698 pcc->pc.destruct = genericDestruct;
1699 pcc->pc.print = genericPrint;
1702 pcc->comment = Safe_strdup(cP);
1704 pcc->comment = NULL;
1706 return ( (pCode *)pcc);
1710 /*-----------------------------------------------------------------*/
1711 /* newpCodeFunction - */
1712 /*-----------------------------------------------------------------*/
1715 pCode *newpCodeFunction(char *mod,char *f)
1719 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1720 //_ALLOC(pcf,sizeof(pCodeFunction));
1722 pcf->pc.type = PC_FUNCTION;
1723 pcf->pc.prev = pcf->pc.next = NULL;
1724 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1727 // pcf->pc.analyze = genericAnalyze;
1728 pcf->pc.destruct = genericDestruct;
1729 pcf->pc.print = pCodePrintFunction;
1734 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1735 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1736 strcpy(pcf->modname,mod);
1738 pcf->modname = NULL;
1741 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1742 pcf->fname = Safe_calloc(1,strlen(f)+1);
1743 strcpy(pcf->fname,f);
1747 return ( (pCode *)pcf);
1751 /*-----------------------------------------------------------------*/
1753 /*-----------------------------------------------------------------*/
1755 void destructpCodeFlow(pCode *pc)
1757 if(!pc || !isPCFL(pc))
1761 free(PCFL(pc)->uses);
1769 pCode *newpCodeFlow(void )
1773 //_ALLOC(pcflow,sizeof(pCodeFlow));
1774 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1776 pcflow->pc.type = PC_FLOW;
1777 pcflow->pc.prev = pcflow->pc.next = NULL;
1778 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1779 pcflow->pc.pb = NULL;
1781 // pcflow->pc.analyze = genericAnalyze;
1782 pcflow->pc.destruct = destructpCodeFlow;
1783 pcflow->pc.print = genericPrint;
1785 pcflow->pc.seq = GpcFlowSeq++;
1788 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1790 pcflow->from = pcflow->to = NULL;
1792 pcflow->inCond = PCC_NONE;
1793 pcflow->outCond = PCC_NONE;
1795 pcflow->firstBank = -1;
1796 pcflow->lastBank = -1;
1798 pcflow->FromConflicts = 0;
1799 pcflow->ToConflicts = 0;
1802 return ( (pCode *)pcflow);
1806 /*-----------------------------------------------------------------*/
1807 /*-----------------------------------------------------------------*/
1808 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1810 pCodeFlowLink *pcflowLink;
1812 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1814 pcflowLink->pcflow = pcflow;
1815 pcflowLink->bank_conflict = 0;
1820 /*-----------------------------------------------------------------*/
1821 /* newpCodeCSource - create a new pCode Source Symbol */
1822 /*-----------------------------------------------------------------*/
1824 pCode *newpCodeCSource(int ln, char *f, char *l)
1829 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1831 pccs->pc.type = PC_CSOURCE;
1832 pccs->pc.prev = pccs->pc.next = NULL;
1835 pccs->pc.destruct = genericDestruct;
1836 pccs->pc.print = genericPrint;
1838 pccs->line_number = ln;
1840 pccs->line = Safe_strdup(l);
1845 pccs->file_name = Safe_strdup(f);
1847 pccs->file_name = NULL;
1849 return ( (pCode *)pccs);
1852 /*-----------------------------------------------------------------*/
1853 /* pCodeLabelDestruct - free memory used by a label. */
1854 /*-----------------------------------------------------------------*/
1855 static void pCodeLabelDestruct(pCode *pc)
1861 if((pc->type == PC_LABEL) && PCL(pc)->label)
1862 free(PCL(pc)->label);
1868 pCode *newpCodeLabel(char *name, int key)
1874 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1876 pcl->pc.type = PC_LABEL;
1877 pcl->pc.prev = pcl->pc.next = NULL;
1878 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1881 // pcl->pc.analyze = genericAnalyze;
1882 pcl->pc.destruct = pCodeLabelDestruct;
1883 pcl->pc.print = pCodePrintLabel;
1889 sprintf(s,"_%05d_DS_",key);
1894 pcl->label = Safe_strdup(s);
1897 return ( (pCode *)pcl);
1902 /*-----------------------------------------------------------------*/
1903 /* newpBlock - create and return a pointer to a new pBlock */
1904 /*-----------------------------------------------------------------*/
1905 pBlock *newpBlock(void)
1910 PpB = Safe_calloc(1,sizeof(pBlock) );
1911 PpB->next = PpB->prev = NULL;
1913 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1914 PpB->tregisters = NULL;
1921 /*-----------------------------------------------------------------*/
1922 /* newpCodeChain - create a new chain of pCodes */
1923 /*-----------------------------------------------------------------*
1925 * This function will create a new pBlock and the pointer to the
1926 * pCode that is passed in will be the first pCode in the block.
1927 *-----------------------------------------------------------------*/
1930 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1933 pBlock *pB = newpBlock();
1935 pB->pcHead = pB->pcTail = pc;
1942 /*-----------------------------------------------------------------*/
1943 /* newpCodeOpLabel - Create a new label given the key */
1944 /* Note, a negative key means that the label is part of wild card */
1945 /* (and hence a wild card label) used in the pCodePeep */
1946 /* optimizations). */
1947 /*-----------------------------------------------------------------*/
1949 pCodeOp *newpCodeOpLabel(char *name, int key)
1952 static int label_key=-1;
1956 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1957 pcop->type = PO_LABEL;
1962 sprintf(s=buffer,"_%05d_DS_",key);
1964 s = name, key = label_key--;
1967 pcop->name = Safe_strdup(s);
1969 ((pCodeOpLabel *)pcop)->key = key;
1974 /*-----------------------------------------------------------------*/
1975 /*-----------------------------------------------------------------*/
1976 pCodeOp *newpCodeOpLit(int lit)
1982 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1983 pcop->type = PO_LITERAL;
1987 sprintf(s,"0x%02x",lit);
1989 pcop->name = Safe_strdup(s);
1992 ((pCodeOpLit *)pcop)->lit = lit;
1997 /*-----------------------------------------------------------------*/
1998 /*-----------------------------------------------------------------*/
1999 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2003 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2004 pcop->type = PO_IMMEDIATE;
2006 pcop->name = Safe_strdup(name);
2007 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2013 PCOI(pcop)->index = index;
2014 PCOI(pcop)->offset = offset;
2015 PCOI(pcop)->_const = code_space;
2020 /*-----------------------------------------------------------------*/
2021 /*-----------------------------------------------------------------*/
2022 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2028 if(!pcwb || !subtype) {
2029 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2033 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2034 pcop->type = PO_WILD;
2035 sprintf(s,"%%%d",id);
2036 pcop->name = Safe_strdup(s);
2038 PCOW(pcop)->id = id;
2039 PCOW(pcop)->pcwb = pcwb;
2040 PCOW(pcop)->subtype = subtype;
2041 PCOW(pcop)->matched = NULL;
2046 /*-----------------------------------------------------------------*/
2047 /*-----------------------------------------------------------------*/
2048 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2052 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2053 pcop->type = PO_GPR_BIT;
2055 pcop->name = Safe_strdup(s);
2059 PCORB(pcop)->bit = bit;
2060 PCORB(pcop)->inBitSpace = inBitSpace;
2065 /*-----------------------------------------------------------------*
2066 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2068 * If rIdx >=0 then a specific register from the set of registers
2069 * will be selected. If rIdx <0, then a new register will be searched
2071 *-----------------------------------------------------------------*/
2073 pCodeOp *newpCodeOpReg(int rIdx)
2077 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2082 PCOR(pcop)->rIdx = rIdx;
2083 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2085 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2088 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2089 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2092 pcop->type = PCOR(pcop)->r->pc_type;
2097 pCodeOp *newpCodeOpRegFromStr(char *name)
2101 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2102 PCOR(pcop)->r = allocRegByName(name, 1);
2103 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2104 pcop->type = PCOR(pcop)->r->pc_type;
2105 pcop->name = PCOR(pcop)->r->name;
2110 /*-----------------------------------------------------------------*/
2111 /*-----------------------------------------------------------------*/
2113 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2120 pcop = newpCodeOpBit(name, -1,0);
2124 pcop = newpCodeOpLit(-1);
2128 pcop = newpCodeOpLabel(NULL,-1);
2131 pcop = newpCodeOpReg(-1);
2135 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2138 pcop->name = Safe_strdup(name);
2146 /*-----------------------------------------------------------------*/
2147 /*-----------------------------------------------------------------*/
2148 void pCodeConstString(char *name, char *value)
2152 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2157 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2161 sprintf(buffer,"; %s = %s",name,value);
2163 addpCode2pBlock(pb,newpCodeCharP(buffer));
2164 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2167 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2173 /*-----------------------------------------------------------------*/
2174 /*-----------------------------------------------------------------*/
2175 void pCodeReadCodeTable(void)
2179 fprintf(stderr, " %s\n",__FUNCTION__);
2181 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2185 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2186 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2187 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2188 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2190 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2191 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2192 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2193 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2198 /*-----------------------------------------------------------------*/
2199 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2200 /*-----------------------------------------------------------------*/
2201 void addpCode2pBlock(pBlock *pb, pCode *pc)
2204 /* If this is the first pcode to be added to a block that
2205 * was initialized with a NULL pcode, then go ahead and
2206 * make this pcode the head and tail */
2207 pb->pcHead = pb->pcTail = pc;
2209 pb->pcTail->next = pc;
2210 pc->prev = pb->pcTail;
2217 /*-----------------------------------------------------------------*/
2218 /* addpBlock - place a pBlock into the pFile */
2219 /*-----------------------------------------------------------------*/
2220 void addpBlock(pBlock *pb)
2222 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2225 /* First time called, we'll pass through here. */
2226 //_ALLOC(the_pFile,sizeof(pFile));
2227 the_pFile = Safe_calloc(1,sizeof(pFile));
2228 the_pFile->pbHead = the_pFile->pbTail = pb;
2229 the_pFile->functions = NULL;
2233 the_pFile->pbTail->next = pb;
2234 pb->prev = the_pFile->pbTail;
2236 the_pFile->pbTail = pb;
2239 /*-----------------------------------------------------------------*/
2240 /* removepBlock - remove a pBlock from the pFile */
2241 /*-----------------------------------------------------------------*/
2242 void removepBlock(pBlock *pb)
2250 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2252 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2255 if(pbs == the_pFile->pbHead)
2256 the_pFile->pbHead = pbs->next;
2258 if (pbs == the_pFile->pbTail)
2259 the_pFile->pbTail = pbs->prev;
2262 pbs->next->prev = pbs->prev;
2265 pbs->prev->next = pbs->next;
2272 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2276 /*-----------------------------------------------------------------*/
2277 /* printpCode - write the contents of a pCode to a file */
2278 /*-----------------------------------------------------------------*/
2279 void printpCode(FILE *of, pCode *pc)
2290 fprintf(of,"warning - unable to print pCode\n");
2293 /*-----------------------------------------------------------------*/
2294 /* printpBlock - write the contents of a pBlock to a file */
2295 /*-----------------------------------------------------------------*/
2296 void printpBlock(FILE *of, pBlock *pb)
2306 for(pc = pb->pcHead; pc; pc = pc->next)
2311 /*-----------------------------------------------------------------*/
2313 /* pCode processing */
2317 /*-----------------------------------------------------------------*/
2319 static void unlinkPC(pCode *pc)
2325 fprintf(stderr,"Unlinking: ");
2326 printpCode(stderr, pc);
2329 pc->prev->next = pc->next;
2331 pc->next->prev = pc->prev;
2333 pc->prev = pc->next = NULL;
2336 static void genericDestruct(pCode *pc)
2338 //fprintf(stderr,"warning, calling default pCode destructor\n");
2347 /*-----------------------------------------------------------------*/
2348 /*-----------------------------------------------------------------*/
2349 void pBlockRegs(FILE *of, pBlock *pb)
2354 r = setFirstItem(pb->tregisters);
2356 r = setNextItem(pb->tregisters);
2361 /*-----------------------------------------------------------------*/
2362 /*-----------------------------------------------------------------*/
2363 char *get_op(pCodeOp *pcop)
2366 static char buffer[50];
2372 switch(pcop->type) {
2375 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2376 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2378 return PCOR(pcop)->r->name;
2381 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2382 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2386 // return PCOR(pcc->pcop)->r)->name;
2389 size = sizeof(buffer);
2390 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2391 if(PCOI(pcop)->_const) {
2393 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2394 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2397 8 * PCOI(pcop)->offset );
2399 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2402 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2403 SAFE_snprintf(&s,&size,"(%s + %d)",
2405 PCOI(pcop)->index );
2407 SAFE_snprintf(&s,&size,"%s",pcop->name);
2414 size = sizeof(buffer);
2415 if( PCOR(pcop)->instance) {
2416 SAFE_snprintf(&s,&size,"(%s + %d)",
2418 PCOR(pcop)->instance );
2419 //fprintf(stderr,"PO_DIR %s\n",buffer);
2421 SAFE_snprintf(&s,&size,"%s",pcop->name);
2431 return "NO operand";
2435 /*-----------------------------------------------------------------*/
2436 /*-----------------------------------------------------------------*/
2437 static char *get_op_from_instruction( pCodeInstruction *pcc)
2441 return get_op(pcc->pcop);
2443 return ("ERROR Null: "__FUNCTION__);
2447 /*-----------------------------------------------------------------*/
2448 /*-----------------------------------------------------------------*/
2449 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2452 fprintf(of,"pcodeopprint- not implemented\n");
2455 /*-----------------------------------------------------------------*/
2456 /*-----------------------------------------------------------------*/
2457 char *pCode2str(char *str, int size, pCode *pc)
2465 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2467 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2469 if(PCI(pc)->isBitInst) {
2470 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2471 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2472 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2473 PCI(pc)->pcop->name ,
2474 PCI(pc)->pcop->name );
2476 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2477 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2478 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2479 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2481 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2482 //PCI(pc)->pcop->t.bit );
2485 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2486 if( PCI(pc)->num_ops == 2)
2487 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2489 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2492 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2494 if( PCI(pc)->num_ops == 2)
2495 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2503 /* assuming that comment ends with a \n */
2504 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2508 /* assuming that inline code ends with a \n */
2509 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2513 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2516 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2519 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2522 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2525 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2534 /*-----------------------------------------------------------------*/
2535 /* genericPrint - the contents of a pCode to a file */
2536 /*-----------------------------------------------------------------*/
2537 static void genericPrint(FILE *of, pCode *pc)
2545 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2549 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2553 // If the opcode has a label, print that first
2555 pBranch *pbl = PCI(pc)->label;
2556 while(pbl && pbl->pc) {
2557 if(pbl->pc->type == PC_LABEL)
2558 pCodePrintLabel(of, pbl->pc);
2564 genericPrint(of,PCODE(PCI(pc)->cline));
2569 pCode2str(str, 256, pc);
2571 fprintf(of,"%s",str);
2574 fprintf(of, "\t;key=%03x",pc->seq);
2576 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2580 pBranch *dpb = pc->to; // debug
2582 switch ( dpb->pc->type) {
2584 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2587 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2590 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2593 fprintf(of, "\t;flow");
2607 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2608 if(PCW(pc)->pci.label)
2609 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2611 if(PCW(pc)->operand) {
2612 fprintf(of,";\toperand ");
2613 pCodeOpPrint(of,PCW(pc)->operand );
2618 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2622 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2626 fprintf(of,"unknown pCode type %d\n",pc->type);
2631 /*-----------------------------------------------------------------*/
2632 /* pCodePrintFunction - prints function begin/end */
2633 /*-----------------------------------------------------------------*/
2635 static void pCodePrintFunction(FILE *of, pCode *pc)
2641 if( ((pCodeFunction *)pc)->modname)
2642 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2644 if(PCF(pc)->fname) {
2645 pBranch *exits = PCF(pc)->to;
2647 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2650 exits = exits->next;
2653 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2656 if((PCF(pc)->from &&
2657 PCF(pc)->from->pc->type == PC_FUNCTION &&
2658 PCF(PCF(pc)->from->pc)->fname) )
2659 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2661 fprintf(of,"; exit point [can't find entry point]\n");
2664 /*-----------------------------------------------------------------*/
2665 /* pCodePrintLabel - prints label */
2666 /*-----------------------------------------------------------------*/
2668 static void pCodePrintLabel(FILE *of, pCode *pc)
2675 fprintf(of,"%s\n",PCL(pc)->label);
2676 else if (PCL(pc)->key >=0)
2677 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2679 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2682 /*-----------------------------------------------------------------*/
2683 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2684 /* remove it if it is found. */
2685 /*-----------------------------------------------------------------*/
2686 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2693 if(pcl->type == PC_OPCODE)
2694 b = PCI(pcl)->label;
2696 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2701 //fprintf (stderr, "%s \n",__FUNCTION__);
2702 //pcl->print(stderr,pcl);
2703 //pc->print(stderr,pc);
2706 //fprintf (stderr, "found label\n");
2710 bprev->next = b->next; /* Not first pCode in chain */
2714 PCI(pcl)->label = b->next; /* First pCode in chain */
2717 return; /* A label can't occur more than once */
2725 /*-----------------------------------------------------------------*/
2726 /*-----------------------------------------------------------------*/
2727 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2743 /*-----------------------------------------------------------------*/
2744 /* pBranchLink - given two pcodes, this function will link them */
2745 /* together through their pBranches */
2746 /*-----------------------------------------------------------------*/
2747 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2751 // Declare a new branch object for the 'from' pCode.
2753 //_ALLOC(b,sizeof(pBranch));
2754 b = Safe_calloc(1,sizeof(pBranch));
2755 b->pc = PCODE(t); // The link to the 'to' pCode.
2758 f->to = pBranchAppend(f->to,b);
2760 // Now do the same for the 'to' pCode.
2762 //_ALLOC(b,sizeof(pBranch));
2763 b = Safe_calloc(1,sizeof(pBranch));
2767 t->from = pBranchAppend(t->from,b);
2772 /*-----------------------------------------------------------------*/
2773 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2775 /*-----------------------------------------------------------------*/
2776 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2789 /*-----------------------------------------------------------------*/
2790 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2791 /*-----------------------------------------------------------------*/
2792 static void pCodeUnlink(pCode *pc)
2797 if(!pc->prev || !pc->next) {
2798 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2802 /* first remove the pCode from the chain */
2803 pc->prev->next = pc->next;
2804 pc->next->prev = pc->prev;
2806 /* Now for the hard part... */
2808 /* Remove the branches */
2812 pc1 = pb1->pc; /* Get the pCode that branches to the
2813 * one we're unlinking */
2815 /* search for the link back to this pCode (the one we're
2817 if(pb2 = pBranchFind(pc1->to,pc)) {
2818 pb2->pc = pc->to->pc; // make the replacement
2820 /* if the pCode we're unlinking contains multiple 'to'
2821 * branches (e.g. this a skip instruction) then we need
2822 * to copy these extra branches to the chain. */
2824 pBranchAppend(pb2, pc->to->next);
2833 /*-----------------------------------------------------------------*/
2834 /*-----------------------------------------------------------------*/
2836 static void genericAnalyze(pCode *pc)
2846 // Go through the pCodes that are in pCode chain and link
2847 // them together through the pBranches. Note, the pCodes
2848 // are linked together as a contiguous stream like the
2849 // assembly source code lines. The linking here mimics this
2850 // except that comments are not linked in.
2852 pCode *npc = pc->next;
2854 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2855 pBranchLink(pc,npc);
2860 /* reached the end of the pcode chain without finding
2861 * an instruction we could link to. */
2865 fprintf(stderr,"analyze PC_FLOW\n");
2872 /*-----------------------------------------------------------------*/
2873 /*-----------------------------------------------------------------*/
2874 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2878 if(pc->type == PC_LABEL) {
2879 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2882 if(pc->type == PC_OPCODE) {
2883 pbr = PCI(pc)->label;
2885 if(pbr->pc->type == PC_LABEL) {
2886 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2896 /*-----------------------------------------------------------------*/
2897 /*-----------------------------------------------------------------*/
2898 int checkLabel(pCode *pc)
2902 if(pc && isPCI(pc)) {
2903 pbr = PCI(pc)->label;
2905 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2915 /*-----------------------------------------------------------------*/
2916 /* findLabelinpBlock - Search the pCode for a particular label */
2917 /*-----------------------------------------------------------------*/
2918 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2925 for(pc = pb->pcHead; pc; pc = pc->next)
2926 if(compareLabel(pc,pcop_label))
2932 /*-----------------------------------------------------------------*/
2933 /* findLabel - Search the pCode for a particular label */
2934 /*-----------------------------------------------------------------*/
2935 pCode * findLabel(pCodeOpLabel *pcop_label)
2943 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2944 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2948 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2952 /*-----------------------------------------------------------------*/
2953 /* findNextpCode - given a pCode, find the next of type 'pct' */
2954 /* in the linked list */
2955 /*-----------------------------------------------------------------*/
2956 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2969 /*-----------------------------------------------------------------*/
2970 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2971 /* in the linked list */
2972 /*-----------------------------------------------------------------*/
2973 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2985 /*-----------------------------------------------------------------*/
2986 /* findNextInstruction - given a pCode, find the next instruction */
2987 /* in the linked list */
2988 /*-----------------------------------------------------------------*/
2989 pCode * findNextInstruction(pCode *pci)
2994 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2998 fprintf(stderr,"findNextInstruction: ");
2999 printpCode(stderr, pc);
3004 //fprintf(stderr,"Couldn't find instruction\n");
3008 /*-----------------------------------------------------------------*/
3009 /* findNextInstruction - given a pCode, find the next instruction */
3010 /* in the linked list */
3011 /*-----------------------------------------------------------------*/
3012 pCode * findPrevInstruction(pCode *pci)
3014 return findPrevpCode(pci, PC_OPCODE);
3017 /*-----------------------------------------------------------------*/
3018 /* findFunctionEnd - given a pCode find the end of the function */
3019 /* that contains it */
3020 /*-----------------------------------------------------------------*/
3021 pCode * findFunctionEnd(pCode *pc)
3025 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3031 fprintf(stderr,"Couldn't find function end\n");
3036 /*-----------------------------------------------------------------*/
3037 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3038 /* instruction with which it is associated. */
3039 /*-----------------------------------------------------------------*/
3040 static void AnalyzeLabel(pCode *pc)
3049 static void AnalyzeGOTO(pCode *pc)
3052 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3056 static void AnalyzeSKIP(pCode *pc)
3059 pBranchLink(pc,findNextInstruction(pc->next));
3060 pBranchLink(pc,findNextInstruction(pc->next->next));
3064 static void AnalyzeRETURN(pCode *pc)
3067 // branch_link(pc,findFunctionEnd(pc->next));
3073 /*-----------------------------------------------------------------*/
3074 /*-----------------------------------------------------------------*/
3075 regs * getRegFromInstruction(pCode *pc)
3080 PCI(pc)->num_ops == 0 )
3083 switch(PCI(pc)->pcop->type) {
3086 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3090 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3091 return PCOR(PCI(pc)->pcop)->r;
3094 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3095 return NULL; // PCOR(PCI(pc)->pcop)->r;
3098 return PCOR(PCI(pc)->pcop)->r;
3101 //fprintf(stderr, "getRegFromInstruction - dir\n");
3102 return PCOR(PCI(pc)->pcop)->r;
3104 //fprintf(stderr, "getRegFromInstruction - literal\n");
3108 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3109 //genericPrint(stderr, pc);
3117 /*-----------------------------------------------------------------*/
3118 /*-----------------------------------------------------------------*/
3120 void AnalyzepBlock(pBlock *pb)
3127 /* Find all of the registers used in this pBlock
3128 * by looking at each instruction and examining it's
3131 for(pc = pb->pcHead; pc; pc = pc->next) {
3133 /* Is this an instruction with operands? */
3134 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3136 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3138 /* Loop through all of the registers declared so far in
3139 this block and see if we find this one there */
3141 regs *r = setFirstItem(pb->tregisters);
3144 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3145 PCOR(PCI(pc)->pcop)->r = r;
3148 r = setNextItem(pb->tregisters);
3152 /* register wasn't found */
3153 r = Safe_calloc(1, sizeof(regs));
3154 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3155 addSet(&pb->tregisters, r);
3156 PCOR(PCI(pc)->pcop)->r = r;
3157 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3159 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3162 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3163 if(PCOR(PCI(pc)->pcop)->r) {
3164 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3165 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3167 if(PCI(pc)->pcop->name)
3168 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3170 fprintf(stderr,"ERROR: NULL register\n");
3179 /*-----------------------------------------------------------------*/
3181 /*-----------------------------------------------------------------*/
3182 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3184 void InsertpFlow(pCode *pc, pCode **pflow)
3186 PCFL(*pflow)->end = pc;
3188 if(!pc || !pc->next)
3191 *pflow = newpCodeFlow();
3192 pCodeInsertAfter(pc, *pflow);
3195 /*-----------------------------------------------------------------*/
3196 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3197 /* the flow blocks. */
3199 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3200 * point the instruction flow changes.
3202 /*-----------------------------------------------------------------*/
3203 void BuildFlow(pBlock *pb)
3206 pCode *last_pci=NULL;
3213 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3214 /* Insert a pCodeFlow object at the beginning of a pBlock */
3216 pflow = newpCodeFlow(); /* Create a new Flow object */
3217 pflow->next = pb->pcHead; /* Make the current head the next object */
3218 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3219 pb->pcHead = pflow; /* Make the Flow object the head */
3222 for( pc = findNextInstruction(pb->pcHead);
3224 pc=findNextInstruction(pc)) {
3227 PCI(pc)->pcflow = PCFL(pflow);
3229 //fprintf(stderr," build: ");
3230 //pflow->print(stderr,pflow);
3232 if( PCI(pc)->isSkip) {
3234 /* The two instructions immediately following this one
3235 * mark the beginning of a new flow segment */
3237 while(pc && PCI(pc)->isSkip) {
3239 PCI(pc)->pcflow = PCFL(pflow);
3243 InsertpFlow(pc, &pflow);
3244 pc=findNextInstruction(pc->next);
3252 PCI(pc)->pcflow = PCFL(pflow);
3254 InsertpFlow(pc, &pflow);
3256 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3258 InsertpFlow(pc, &pflow);
3261 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3263 /* This instruction marks the beginning of a
3264 * new flow segment */
3268 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3270 PCI(pc)->pcflow = PCFL(pflow);
3277 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3278 PCFL(pflow)->end = pb->pcTail;
3281 /*-------------------------------------------------------------------*/
3282 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3283 /* the flow blocks. */
3285 * unBuildFlow removes pCodeFlow objects from a pCode chain
3287 /*-----------------------------------------------------------------*/
3288 void unBuildFlow(pBlock *pb)
3297 pCode *pcn = pc->next;
3301 PCI(pc)->pcflow = NULL;
3303 } else if(isPCFL(pc)) {
3313 /*-----------------------------------------------------------------*/
3314 /*-----------------------------------------------------------------*/
3315 void dumpCond(int cond)
3318 static char *pcc_str[] = {
3332 int ncond = sizeof(pcc_str) / sizeof(char *);
3335 fprintf(stderr, "0x%04X\n",cond);
3337 for(i=0,j=1; i<ncond; i++, j<<=1)
3339 fprintf(stderr, " %s\n",pcc_str[i]);
3343 /*-----------------------------------------------------------------*/
3344 /*-----------------------------------------------------------------*/
3345 void FlowStats(pCodeFlow *pcflow)
3353 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3355 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3358 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3363 fprintf(stderr, " FlowStats inCond: ");
3364 dumpCond(pcflow->inCond);
3365 fprintf(stderr, " FlowStats outCond: ");
3366 dumpCond(pcflow->outCond);
3370 /*-----------------------------------------------------------------*
3371 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3372 * if it affects the banking bits.
3374 * return: -1 == Banking bits are unaffected by this pCode.
3376 * return: > 0 == Banking bits are affected.
3378 * If the banking bits are affected, then the returned value describes
3379 * which bits are affected and how they're affected. The lower half
3380 * of the integer maps to the bits that are affected, the upper half
3381 * to whether they're set or cleared.
3383 *-----------------------------------------------------------------*/
3384 #define SET_BANK_BIT (1 << 16)
3385 #define CLR_BANK_BIT 0
3387 int isBankInstruction(pCode *pc)
3395 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3397 /* Check to see if the register banks are changing */
3398 if(PCI(pc)->isModReg) {
3400 pCodeOp *pcop = PCI(pc)->pcop;
3401 switch(PCI(pc)->op) {
3404 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3405 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3406 return SET_BANK_BIT | PIC_RP0_BIT;
3409 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3410 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3411 return CLR_BANK_BIT | PIC_RP0_BIT;
3416 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3417 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3418 return CLR_BANK_BIT | PIC_RP1_BIT;
3420 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3421 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3422 return CLR_BANK_BIT | PIC_RP1_BIT;
3426 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3427 //genericPrint(stderr, pc);
3438 /*-----------------------------------------------------------------*/
3439 /*-----------------------------------------------------------------*/
3440 void FillFlow(pCodeFlow *pcflow)
3449 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3451 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3454 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3461 isBankInstruction(pc);
3463 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3467 fprintf(stderr, " FillFlow - Bad end of flow\n");
3469 fprintf(stderr, " FillFlow - Ending flow with\n ");
3470 pc->print(stderr,pc);
3473 fprintf(stderr, " FillFlow inCond: ");
3474 dumpCond(pcflow->inCond);
3475 fprintf(stderr, " FillFlow outCond: ");
3476 dumpCond(pcflow->outCond);
3480 /*-----------------------------------------------------------------*/
3481 /*-----------------------------------------------------------------*/
3482 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3484 pCodeFlowLink *fromLink, *toLink;
3486 if(!from || !to || !to->pcflow || !from->pcflow)
3489 fromLink = newpCodeFlowLink(from->pcflow);
3490 toLink = newpCodeFlowLink(to->pcflow);
3492 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3493 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3497 /*-----------------------------------------------------------------*/
3498 /*-----------------------------------------------------------------*/
3499 void LinkFlow(pBlock *pb)
3505 //fprintf(stderr,"linkflow \n");
3507 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3509 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3512 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3514 //fprintf(stderr," link: ");
3515 //pcflow->print(stderr,pcflow);
3517 //FillFlow(PCFL(pcflow));
3519 pc = PCFL(pcflow)->end;
3521 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3522 if(isPCI_SKIP(pc)) {
3523 //fprintf(stderr, "ends with skip\n");
3524 //pc->print(stderr,pc);
3525 pct=findNextInstruction(pc->next);
3526 LinkFlow_pCode(PCI(pc),PCI(pct));
3527 pct=findNextInstruction(pct->next);
3528 LinkFlow_pCode(PCI(pc),PCI(pct));
3532 if(isPCI_BRANCH(pc)) {
3533 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3535 //fprintf(stderr, "ends with branch\n ");
3536 //pc->print(stderr,pc);
3538 if(!(pcol && isPCOLAB(pcol))) {
3539 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3540 pc->print(stderr,pc);
3541 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3546 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3547 LinkFlow_pCode(PCI(pc),PCI(pct));
3549 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3555 //fprintf(stderr, "ends with non-branching instruction:\n");
3556 //pc->print(stderr,pc);
3558 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3564 //fprintf(stderr, "ends with unknown\n");
3565 //pc->print(stderr,pc);
3569 //fprintf(stderr, "ends with nothing: ERROR\n");
3574 /*-----------------------------------------------------------------*/
3575 /*-----------------------------------------------------------------*/
3576 int isPCinFlow(pCode *pc, pCode *pcflow)
3582 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3585 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3591 /*-----------------------------------------------------------------*/
3592 /*-----------------------------------------------------------------*/
3593 void BanksUsedFlow2(pCode *pcflow)
3602 if(!isPCFL(pcflow)) {
3603 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3607 pc = findNextInstruction(pcflow->next);
3609 PCFL(pcflow)->lastBank = -1;
3611 while(isPCinFlow(pc,pcflow)) {
3613 int bank_selected = isBankInstruction(pc);
3615 //if(PCI(pc)->pcflow)
3616 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3618 if(bank_selected > 0) {
3619 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3621 /* This instruction is modifying banking bits before accessing registers */
3623 PCFL(pcflow)->firstBank = -1;
3625 if(PCFL(pcflow)->lastBank == -1)
3626 PCFL(pcflow)->lastBank = 0;
3628 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3629 if(bank_selected & SET_BANK_BIT)
3630 PCFL(pcflow)->lastBank |= bank;
3634 reg = getRegFromInstruction(pc);
3636 if(reg && !isREGinBank(reg, bank)) {
3637 int allbanks = REGallBanks(reg);
3639 PCFL(pcflow)->firstBank = allbanks;
3641 PCFL(pcflow)->lastBank = allbanks;
3648 pc = findNextInstruction(pc->next);
3651 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3652 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3657 /*-----------------------------------------------------------------*/
3658 /*-----------------------------------------------------------------*/
3659 void BanksUsedFlow(pBlock *pb)
3664 //pb->pcHead->print(stderr, pb->pcHead);
3666 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3667 //pcflow->print(stderr,pcflow);
3669 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3671 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3673 BanksUsedFlow2(pcflow);
3679 /*-----------------------------------------------------------------*/
3680 /*-----------------------------------------------------------------*/
3681 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3689 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3691 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3692 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3694 pCodeInsertAfter(pc->prev, new_pc);
3696 /* Move the label, if there is one */
3698 if(PCI(pc)->label) {
3699 PCI(new_pc)->label = PCI(pc)->label;
3700 PCI(pc)->label = NULL;
3703 /* The new instruction has the same pcflow block */
3704 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3707 /*-----------------------------------------------------------------*/
3708 /*-----------------------------------------------------------------*/
3709 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3720 pc = findNextInstruction(pcfl->pc.next);
3722 while(isPCinFlow(pc,PCODE(pcfl))) {
3725 reg = getRegFromInstruction(pc);
3728 fprintf(stderr, " %s ",reg->name);
3729 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3734 if(reg && REG_BANK(reg)!=cur_bank) {
3735 /* Examine the instruction before this one to make sure it is
3736 * not a skip type instruction */
3737 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3738 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3739 int b = cur_bank ^ REG_BANK(reg);
3741 //fprintf(stderr, "Cool! can switch banks\n");
3742 cur_bank = REG_BANK(reg);
3747 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3750 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3751 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3755 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3756 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3758 insertBankSwitch(pc, -1, -1);
3761 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3762 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3763 pCodeInsertAfter(pc->prev, new_pc);
3764 if(PCI(pc)->label) {
3765 PCI(new_pc)->label = PCI(pc)->label;
3766 PCI(pc)->label = NULL;
3770 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3771 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3772 pCodeInsertAfter(pc, new_pc);
3778 //fprintf(stderr, "Bummer can't switch banks\n");
3784 pc = findNextInstruction(pc->next);
3788 if(pcprev && cur_bank) {
3789 /* Brute force - make sure that we point to bank 0 at the
3790 * end of each flow block */
3791 new_pc = newpCode(POC_BCF,
3792 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3793 pCodeInsertAfter(pcprev, new_pc);
3799 /*-----------------------------------------------------------------*/
3800 /*int compareBankFlow - compare the banking requirements between */
3802 /*-----------------------------------------------------------------*/
3803 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3806 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3809 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3812 if(pcflow->firstBank == -1)
3816 if(pcflowLink->pcflow->firstBank == -1) {
3817 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3818 pcflowLink->pcflow->to :
3819 pcflowLink->pcflow->from);
3820 return compareBankFlow(pcflow, pctl, toORfrom);
3824 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3827 pcflowLink->bank_conflict++;
3828 pcflowLink->pcflow->FromConflicts++;
3829 pcflow->ToConflicts++;
3832 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3835 pcflowLink->bank_conflict++;
3836 pcflowLink->pcflow->ToConflicts++;
3837 pcflow->FromConflicts++;
3841 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3842 pcflowLink->pcflow->pc.seq,
3843 pcflowLink->pcflow->FromConflicts,
3844 pcflowLink->pcflow->ToConflicts);
3849 /*-----------------------------------------------------------------*/
3850 /*-----------------------------------------------------------------*/
3851 void FixBankFlow(pBlock *pb)
3855 pCodeFlowLink *pcfl;
3857 pCode *pcflow_max_To=NULL;
3858 pCode *pcflow_max_From=NULL;
3859 int max_ToConflicts=0;
3860 int max_FromConflicts=0;
3862 //fprintf(stderr,"Fix Bank flow \n");
3863 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3867 First loop through all of the flow objects in this pcode block
3868 and fix the ones that have banking conflicts between the
3872 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3874 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3876 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3878 if(!isPCFL(pcflow)) {
3879 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3883 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3884 PCFL(pcflow)->firstBank >= 0 &&
3885 PCFL(pcflow)->lastBank >= 0 ) {
3887 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3888 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3890 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3891 BanksUsedFlow2(pcflow);
3896 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3898 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3900 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3905 if(!isPCFL(pcflow)) {
3906 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3910 PCFL(pcflow)->FromConflicts = 0;
3911 PCFL(pcflow)->ToConflicts = 0;
3916 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3917 pcfl = setFirstItem(PCFL(pcflow)->from);
3920 pc = PCODE(pcfl->pcflow);
3923 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3924 pc->print(stderr,pc);
3927 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3930 pcfl=setNextItem(PCFL(pcflow)->from);
3933 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3934 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3936 FixRegisterBankingInFlow(PCFL(pcflow),0);
3937 BanksUsedFlow2(pcflow);
3939 continue; /* Don't need to check the flow from here - it's already been fixed */
3946 pcfl = setFirstItem(PCFL(pcflow)->to);
3949 pc = PCODE(pcfl->pcflow);
3951 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3952 pc->print(stderr,pc);
3955 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
3958 pcfl=setNextItem(PCFL(pcflow)->to);
3961 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
3962 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3964 FixRegisterBankingInFlow(PCFL(pcflow),0);
3965 BanksUsedFlow2(pcflow);
3970 Loop through the flow objects again and find the ones with the
3974 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3976 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3978 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
3979 pcflow_max_To = pcflow;
3981 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
3982 pcflow_max_From = pcflow;
3986 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
3987 PCFL(pcflow_max_To)->pc.seq,
3988 PCFL(pcflow_max_To)->ToConflicts);
3991 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
3992 PCFL(pcflow_max_From)->pc.seq,
3993 PCFL(pcflow_max_From)->FromConflicts);
3997 /*-----------------------------------------------------------------*/
3998 /*-----------------------------------------------------------------*/
3999 void DumpFlow(pBlock *pb)
4003 pCodeFlowLink *pcfl;
4006 fprintf(stderr,"Dump flow \n");
4007 pb->pcHead->print(stderr, pb->pcHead);
4009 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4010 pcflow->print(stderr,pcflow);
4012 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4014 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4016 if(!isPCFL(pcflow)) {
4017 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4020 fprintf(stderr,"dumping: ");
4021 pcflow->print(stderr,pcflow);
4022 FlowStats(PCFL(pcflow));
4024 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4026 pc = PCODE(pcfl->pcflow);
4028 fprintf(stderr, " from seq %d:\n",pc->seq);
4030 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4031 pc->print(stderr,pc);
4036 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4038 pc = PCODE(pcfl->pcflow);
4040 fprintf(stderr, " to seq %d:\n",pc->seq);
4042 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4043 pc->print(stderr,pc);
4052 /*-----------------------------------------------------------------*/
4053 /*-----------------------------------------------------------------*/
4054 int OptimizepBlock(pBlock *pb)
4059 if(!pb || !peepOptimizing)
4062 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4064 for(pc = pb->pcHead; pc; pc = pc->next)
4065 matches += pCodePeepMatchRule(pc);
4068 pc = findNextInstruction(pb->pcHead);
4073 if(pCodePeepMatchRule(pc)) {
4078 pc = findNextInstruction(pcprev->next);
4080 pc = findNextInstruction(pb->pcHead);
4082 pc = findNextInstruction(pc->next);
4086 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4091 /*-----------------------------------------------------------------*/
4092 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4093 /*-----------------------------------------------------------------*/
4094 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4098 for(pc = pcs; pc; pc = pc->next) {
4100 if((pc->type == PC_OPCODE) &&
4102 (PCI(pc)->pcop->type == PO_LABEL) &&
4103 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4111 /*-----------------------------------------------------------------*/
4112 /*-----------------------------------------------------------------*/
4113 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4118 (PCI(pc)->pcop->type == PO_LABEL)) {
4120 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4122 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4124 free(pcol->pcop.name);
4126 sprintf(buffer,"_%05d_DS_",pcl->key);
4128 pcol->pcop.name = Safe_strdup(buffer);
4129 pcol->key = pcl->key;
4130 //pc->print(stderr,pc);
4137 /*-----------------------------------------------------------------*/
4138 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4139 /* pCode chain if they're not used. */
4140 /*-----------------------------------------------------------------*/
4141 void pBlockRemoveUnusedLabels(pBlock *pb)
4143 pCode *pc; pCodeLabel *pcl;
4148 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4150 pBranch *pbr = PCI(pc)->label;
4151 if(pbr && pbr->next) {
4152 pCode *pcd = pb->pcHead;
4154 //fprintf(stderr, "multiple labels\n");
4155 //pc->print(stderr,pc);
4160 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4161 //fprintf(stderr,"Used by:\n");
4162 //pcd->print(stderr,pcd);
4164 exchangeLabels(PCL(pbr->pc),pcd);
4173 for(pc = pb->pcHead; pc; pc = pc->next) {
4175 if(isPCL(pc)) // pc->type == PC_LABEL)
4177 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4178 pcl = PCL(PCI(pc)->label->pc);
4181 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4183 /* This pCode is a label, so search the pBlock to see if anyone
4186 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4187 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4188 /* Couldn't find an instruction that refers to this label
4189 * So, unlink the pCode label from it's pCode chain
4190 * and destroy the label */
4191 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4193 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4194 if(pc->type == PC_LABEL) {
4196 pCodeLabelDestruct(pc);
4198 unlinkpCodeFromBranch(pc, PCODE(pcl));
4199 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4210 /*-----------------------------------------------------------------*/
4211 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4212 /* chain and put them into pBranches that are */
4213 /* associated with the appropriate pCode */
4215 /*-----------------------------------------------------------------*/
4216 void pBlockMergeLabels(pBlock *pb)
4219 pCode *pc, *pcnext=NULL;
4224 /* First, Try to remove any unused labels */
4225 //pBlockRemoveUnusedLabels(pb);
4227 /* Now loop through the pBlock and merge the labels with the opcodes */
4229 for(pc = pb->pcHead; pc; pc = pc->next) {
4231 if(pc->type == PC_LABEL) {
4233 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4234 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4235 if((pcnext = findNextInstruction(pc) )) {
4237 pCode *pcn = pc->next;
4239 // Unlink the pCode label from it's pCode chain
4242 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4243 // And link it into the instruction's pBranch labels. (Note, since
4244 // it's possible to have multiple labels associated with one instruction
4245 // we must provide a means to accomodate the additional labels. Thus
4246 // the labels are placed into the singly-linked list "label" as
4247 // opposed to being a single member of the pCodeInstruction.)
4249 //_ALLOC(pbr,sizeof(pBranch));
4250 pbr = Safe_calloc(1,sizeof(pBranch));
4255 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4260 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4262 } else if(pc->type == PC_CSOURCE) {
4264 /* merge the source line symbolic info into the next instruction */
4265 if((pcnext = findNextInstruction(pc) )) {
4267 pCode *pcn = pc->next;
4269 // Unlink the pCode label from it's pCode chain
4271 PCI(pcnext)->cline = PCCS(pc);
4272 //fprintf(stderr, "merging CSRC\n");
4273 //genericPrint(stderr,pcnext);
4280 pBlockRemoveUnusedLabels(pb);
4284 /*-----------------------------------------------------------------*/
4285 /*-----------------------------------------------------------------*/
4286 int OptimizepCode(char dbName)
4288 #define MAX_PASSES 4
4297 DFPRINTF((stderr," Optimizing pCode\n"));
4301 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4302 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4303 matches += OptimizepBlock(pb);
4306 while(matches && ++passes < MAX_PASSES);
4311 /*-----------------------------------------------------------------*/
4312 /* popCopyGPR2Bit - copy a pcode operator */
4313 /*-----------------------------------------------------------------*/
4315 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4319 pcop = newpCodeOpBit(pc->name, bitval, 0);
4321 if( !( (pcop->type == PO_LABEL) ||
4322 (pcop->type == PO_LITERAL) ||
4323 (pcop->type == PO_STR) ))
4324 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4332 /*-----------------------------------------------------------------*/
4333 /*-----------------------------------------------------------------*/
4334 int InstructionRegBank(pCode *pc)
4338 if( (reg = getRegFromInstruction(pc)) == NULL)
4341 return REG_BANK(reg);
4346 /*-----------------------------------------------------------------*/
4347 /*-----------------------------------------------------------------*/
4348 void FixRegisterBanking(pBlock *pb)
4360 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4361 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4364 /* loop through all of the flow blocks with in one pblock */
4366 //fprintf(stderr,"Register banking\n");
4369 /* at this point, pc should point to a PC_FLOW object */
4372 /* for each flow block, determine the register banking
4377 //genericPrint(stderr, pc);
4379 reg = getRegFromInstruction(pc);
4382 fprintf(stderr, " %s ",reg->name);
4383 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4387 if(reg && REG_BANK(reg)!=cur_bank) {
4388 /* Examine the instruction before this one to make sure it is
4389 * not a skip type instruction */
4390 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4391 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4392 int b = cur_bank ^ REG_BANK(reg);
4394 //fprintf(stderr, "Cool! can switch banks\n");
4395 cur_bank = REG_BANK(reg);
4397 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4398 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4399 pCodeInsertAfter(pc->prev, new_pc);
4400 if(PCI(pc)->label) {
4401 PCI(new_pc)->label = PCI(pc)->label;
4402 PCI(pc)->label = NULL;
4405 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4406 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4407 pCodeInsertAfter(pc, new_pc);
4413 //fprintf(stderr, "Bummer can't switch banks\n");
4421 // } while(pc && !(isPCFL(pc)));
4426 if(pcprev && cur_bank) {
4427 /* Brute force - make sure that we point to bank 0 at the
4428 * end of each flow block */
4429 new_pc = newpCode(POC_BCF,
4430 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4431 pCodeInsertAfter(pcprev, new_pc);
4437 void pBlockDestruct(pBlock *pb)
4448 /*-----------------------------------------------------------------*/
4449 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4450 /* name dbName and combine them */
4451 /* into one block */
4452 /*-----------------------------------------------------------------*/
4453 void mergepBlocks(char dbName)
4456 pBlock *pb, *pbmerged = NULL,*pbn;
4458 pb = the_pFile->pbHead;
4460 //fprintf(stderr," merging blocks named %c\n",dbName);
4464 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4465 if( getpBlock_dbName(pb) == dbName) {
4467 //fprintf(stderr," merged block %c\n",dbName);
4472 addpCode2pBlock(pbmerged, pb->pcHead);
4473 /* addpCode2pBlock doesn't handle the tail: */
4474 pbmerged->pcTail = pb->pcTail;
4476 pb->prev->next = pbn;
4478 pbn->prev = pb->prev;
4483 //printpBlock(stderr, pbmerged);
4490 /*-----------------------------------------------------------------*/
4491 /* AnalyzeBanking - Called after the memory addresses have been */
4492 /* assigned to the registers. */
4494 /*-----------------------------------------------------------------*/
4495 void AnalyzeBanking(void)
4504 /* Phase 2 - Flow Analysis - Register Banking
4506 * In this phase, the individual flow blocks are examined
4507 * and register banking is fixed.
4510 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4511 //FixRegisterBanking(pb);
4513 /* Phase 2 - Flow Analysis
4515 * In this phase, the pCode is partition into pCodeFlow
4516 * blocks. The flow blocks mark the points where a continuous
4517 * stream of instructions changes flow (e.g. because of
4518 * a call or goto or whatever).
4521 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4525 /* Phase 2 - Flow Analysis - linking flow blocks
4527 * In this phase, the individual flow blocks are examined
4528 * to determine their order of excution.
4531 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4535 /* Phase x - Flow Analysis - Used Banks
4537 * In this phase, the individual flow blocks are examined
4538 * to determine the Register Banks they use
4541 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4544 /* Phase x - Flow Analysis - Used Banks
4546 * In this phase, the individual flow blocks are examined
4547 * to determine the Register Banks they use
4550 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4554 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4558 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4560 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4561 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4562 pcflow = pcflow->next) {
4564 FillFlow(PCFL(pcflow));
4568 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4570 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4571 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4572 pcflow = pcflow->next) {
4574 FlowStats(PCFL(pcflow));
4580 /*-----------------------------------------------------------------*/
4581 /* buildCallTree - look at the flow and extract all of the calls */
4583 /*-----------------------------------------------------------------*/
4584 set *register_usage(pBlock *pb);
4586 void buildCallTree(void )
4597 /* Now build the call tree.
4598 First we examine all of the pCodes for functions.
4599 Keep in mind that the function boundaries coincide
4600 with pBlock boundaries.
4602 The algorithm goes something like this:
4603 We have two nested loops. The outer loop iterates
4604 through all of the pBlocks/functions. The inner
4605 loop iterates through all of the pCodes for
4606 a given pBlock. When we begin iterating through
4607 a pBlock, the variable pc_fstart, pCode of the start
4608 of a function, is cleared. We then search for pCodes
4609 of type PC_FUNCTION. When one is encountered, we
4610 initialize pc_fstart to this and at the same time
4611 associate a new pBranch object that signifies a
4612 branch entry. If a return is found, then this signifies
4613 a function exit point. We'll link the pCodes of these
4614 returns to the matching pc_fstart.
4616 When we're done, a doubly linked list of pBranches
4617 will exist. The head of this list is stored in
4618 `the_pFile', which is the meta structure for all
4619 of the pCode. Look at the printCallTree function
4620 on how the pBranches are linked together.
4623 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4624 pCode *pc_fstart=NULL;
4625 for(pc = pb->pcHead; pc; pc = pc->next) {
4627 if (PCF(pc)->fname) {
4629 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4630 //fprintf(stderr," found main \n");
4631 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4635 pbr = Safe_calloc(1,sizeof(pBranch));
4636 pbr->pc = pc_fstart = pc;
4639 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4641 // Here's a better way of doing the same:
4642 addSet(&pb->function_entries, pc);
4645 // Found an exit point in a function, e.g. return
4646 // (Note, there may be more than one return per function)
4648 pBranchLink(PCF(pc_fstart), PCF(pc));
4650 addSet(&pb->function_exits, pc);
4652 } else if(isCALL(pc)) {
4653 addSet(&pb->function_calls,pc);
4658 /* Re-allocate the registers so that there are no collisions
4659 * between local variables when one function call another */
4661 pic14_deallocateAllRegs();
4663 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4670 /*-----------------------------------------------------------------*/
4671 /* AnalyzepCode - parse the pCode that has been generated and form */
4672 /* all of the logical connections. */
4674 /* Essentially what's done here is that the pCode flow is */
4676 /*-----------------------------------------------------------------*/
4678 void AnalyzepCode(char dbName)
4689 /* Phase 1 - Register allocation and peep hole optimization
4691 * The first part of the analysis is to determine the registers
4692 * that are used in the pCode. Once that is done, the peep rules
4693 * are applied to the code. We continue to loop until no more
4694 * peep rule optimizations are found (or until we exceed the
4695 * MAX_PASSES threshold).
4697 * When done, the required registers will be determined.
4703 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4704 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4706 /* First, merge the labels with the instructions */
4707 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4708 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4710 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4711 //fprintf(stderr," analyze and merging block %c\n",dbName);
4712 pBlockMergeLabels(pb);
4715 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4719 changes = OptimizepCode(dbName);
4721 } while(changes && (i++ < MAX_PASSES));
4726 /*-----------------------------------------------------------------*/
4727 /* ispCodeFunction - returns true if *pc is the pCode of a */
4729 /*-----------------------------------------------------------------*/
4730 bool ispCodeFunction(pCode *pc)
4733 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4739 /*-----------------------------------------------------------------*/
4740 /* findFunction - Search for a function by name (given the name) */
4741 /* in the set of all functions that are in a pBlock */
4742 /* (note - I expect this to change because I'm planning to limit */
4743 /* pBlock's to just one function declaration */
4744 /*-----------------------------------------------------------------*/
4745 pCode *findFunction(char *fname)
4752 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4754 pc = setFirstItem(pb->function_entries);
4757 if((pc->type == PC_FUNCTION) &&
4759 (strcmp(fname, PCF(pc)->fname)==0))
4762 pc = setNextItem(pb->function_entries);
4770 void MarkUsedRegisters(set *regset)
4775 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4776 r2 = pic14_regWithIdx(r1->rIdx);
4782 void pBlockStats(FILE *of, pBlock *pb)
4788 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4790 // for now just print the first element of each set
4791 pc = setFirstItem(pb->function_entries);
4793 fprintf(of,";entry: ");
4796 pc = setFirstItem(pb->function_exits);
4798 fprintf(of,";has an exit\n");
4802 pc = setFirstItem(pb->function_calls);
4804 fprintf(of,";functions called:\n");
4807 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4808 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4810 pc = setNextItem(pb->function_calls);
4814 r = setFirstItem(pb->tregisters);
4816 int n = elementsInSet(pb->tregisters);
4818 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4821 fprintf(of,"; %s\n",r->name);
4822 r = setNextItem(pb->tregisters);
4827 /*-----------------------------------------------------------------*/
4828 /*-----------------------------------------------------------------*/
4830 static void sequencepCode(void)
4836 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4838 pb->seq = GpCodeSequenceNumber+1;
4840 for( pc = pb->pcHead; pc; pc = pc->next)
4841 pc->seq = ++GpCodeSequenceNumber;
4847 /*-----------------------------------------------------------------*/
4848 /*-----------------------------------------------------------------*/
4849 set *register_usage(pBlock *pb)
4852 set *registers=NULL;
4853 set *registersInCallPath = NULL;
4855 /* check recursion */
4857 pc = setFirstItem(pb->function_entries);
4864 if(pc->type != PC_FUNCTION)
4865 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4867 pc = setFirstItem(pb->function_calls);
4868 for( ; pc; pc = setNextItem(pb->function_calls)) {
4870 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4871 char *dest = get_op_from_instruction(PCI(pc));
4873 pcn = findFunction(dest);
4875 registersInCallPath = register_usage(pcn->pb);
4877 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4882 pBlockStats(stderr,pb); // debug
4885 // Mark the registers in this block as used.
4887 MarkUsedRegisters(pb->tregisters);
4888 if(registersInCallPath) {
4889 /* registers were used in the functions this pBlock has called */
4890 /* so now, we need to see if these collide with the ones we are */
4893 regs *r1,*r2, *newreg;
4895 DFPRINTF((stderr,"comparing registers\n"));
4897 r1 = setFirstItem(registersInCallPath);
4900 r2 = setFirstItem(pb->tregisters);
4902 while(r2 && (r1->type != REG_STK)) {
4904 if(r2->rIdx == r1->rIdx) {
4905 newreg = pic14_findFreeReg(REG_GPR);
4909 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4913 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4914 r1->rIdx, newreg->rIdx));
4915 r2->rIdx = newreg->rIdx;
4916 //if(r2->name) free(r2->name);
4918 r2->name = Safe_strdup(newreg->name);
4922 newreg->wasUsed = 1;
4924 r2 = setNextItem(pb->tregisters);
4927 r1 = setNextItem(registersInCallPath);
4930 /* Collisions have been resolved. Now free the registers in the call path */
4931 r1 = setFirstItem(registersInCallPath);
4933 if(r1->type != REG_STK) {
4934 newreg = pic14_regWithIdx(r1->rIdx);
4937 r1 = setNextItem(registersInCallPath);
4941 // MarkUsedRegisters(pb->registers);
4943 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4946 DFPRINTF((stderr,"returning regs\n"));
4948 DFPRINTF((stderr,"not returning regs\n"));
4950 DFPRINTF((stderr,"pBlock after register optim.\n"));
4951 pBlockStats(stderr,pb); // debug
4957 /*-----------------------------------------------------------------*/
4958 /* printCallTree - writes the call tree to a file */
4960 /*-----------------------------------------------------------------*/
4961 void pct2(FILE *of,pBlock *pb,int indent)
4965 // set *registersInCallPath = NULL;
4971 return; //recursion ?
4973 pc = setFirstItem(pb->function_entries);
4980 for(i=0;i<indent;i++) // Indentation
4983 if(pc->type == PC_FUNCTION)
4984 fprintf(of,"%s\n",PCF(pc)->fname);
4989 pc = setFirstItem(pb->function_calls);
4990 for( ; pc; pc = setNextItem(pb->function_calls)) {
4992 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4993 char *dest = get_op_from_instruction(PCI(pc));
4995 pcn = findFunction(dest);
4997 pct2(of,pcn->pb,indent+1);
4999 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5007 /*-----------------------------------------------------------------*/
5008 /* printCallTree - writes the call tree to a file */
5010 /*-----------------------------------------------------------------*/
5012 void printCallTree(FILE *of)
5024 fprintf(of, "\npBlock statistics\n");
5025 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5030 fprintf(of,"Call Tree\n");
5031 pbr = the_pFile->functions;
5035 if(!ispCodeFunction(pc))
5036 fprintf(of,"bug in call tree");
5039 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5041 while(pc->next && !ispCodeFunction(pc->next)) {
5043 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5044 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5052 fprintf(of,"\n**************\n\na better call tree\n");
5053 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5058 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5059 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5065 /*-----------------------------------------------------------------*/
5067 /*-----------------------------------------------------------------*/
5069 void InlineFunction(pBlock *pb)
5077 pc = setFirstItem(pb->function_calls);
5079 for( ; pc; pc = setNextItem(pb->function_calls)) {
5082 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5088 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5090 //fprintf(stderr,"Cool can inline:\n");
5091 //pcn->print(stderr,pcn);
5093 //fprintf(stderr,"recursive call Inline\n");
5094 InlineFunction(pcn->pb);
5095 //fprintf(stderr,"return from recursive call Inline\n");
5098 At this point, *pc points to a CALL mnemonic, and
5099 *pcn points to the function that is being called.
5101 To in-line this call, we need to remove the CALL
5102 and RETURN(s), and link the function pCode in with
5108 /* Remove the CALL */
5112 /* remove callee pBlock from the pBlock linked list */
5113 removepBlock(pcn->pb);
5121 /* Remove the Function pCode */
5122 pct = findNextInstruction(pcn->next);
5124 /* Link the function with the callee */
5125 pc->next = pcn->next;
5126 pcn->next->prev = pc;
5128 /* Convert the function name into a label */
5130 pbr = Safe_calloc(1,sizeof(pBranch));
5131 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5133 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5134 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5136 /* turn all of the return's except the last into goto's */
5137 /* check case for 2 instruction pBlocks */
5138 pce = findNextInstruction(pcn->next);
5140 pCode *pce_next = findNextInstruction(pce->next);
5142 if(pce_next == NULL) {
5143 /* found the last return */
5144 pCode *pc_call_next = findNextInstruction(pc_call->next);
5146 //fprintf(stderr,"found last return\n");
5147 //pce->print(stderr,pce);
5148 pce->prev->next = pc_call->next;
5149 pc_call->next->prev = pce->prev;
5150 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5160 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5166 /*-----------------------------------------------------------------*/
5168 /*-----------------------------------------------------------------*/
5170 void InlinepCode(void)
5180 /* Loop through all of the function definitions and count the
5181 * number of times each one is called */
5182 //fprintf(stderr,"inlining %d\n",__LINE__);
5184 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5186 pc = setFirstItem(pb->function_calls);
5188 for( ; pc; pc = setNextItem(pb->function_calls)) {
5191 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5192 if(pcn && isPCF(pcn)) {
5193 PCF(pcn)->ncalled++;
5196 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5201 //fprintf(stderr,"inlining %d\n",__LINE__);
5203 /* Now, Loop through the function definitions again, but this
5204 * time inline those functions that have only been called once. */
5206 InlineFunction(the_pFile->pbHead);
5207 //fprintf(stderr,"inlining %d\n",__LINE__);
5209 for(pb = the_pFile->pbHead; pb; pb = pb->next)