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;
74 /* Hardcoded flags to change the behavior of the PIC port */
75 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
76 static int functionInlining = 1; /* inline functions if nonzero */
78 static int GpCodeSequenceNumber = 1;
79 static int GpcFlowSeq = 1;
81 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE))
82 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch)
83 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip)
84 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst)
85 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW))
86 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION))
87 #define isPCL(x) ((PCODE(x)->type == PC_LABEL))
88 #define isPCW(x) ((PCODE(x)->type == PC_WILD))
89 #define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE))
91 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL))
92 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
94 #define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL)
96 /****************************************************************/
97 /* Forward declarations */
98 /****************************************************************/
100 static void unlinkPC(pCode *pc);
102 static void genericAnalyze(pCode *pc);
103 static void AnalyzeGOTO(pCode *pc);
104 static void AnalyzeSKIP(pCode *pc);
105 static void AnalyzeRETURN(pCode *pc);
108 static void genericDestruct(pCode *pc);
109 static void genericPrint(FILE *of,pCode *pc);
111 static void pCodePrintLabel(FILE *of, pCode *pc);
112 static void pCodePrintFunction(FILE *of, pCode *pc);
113 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
114 static char *get_op_from_instruction( pCodeInstruction *pcc);
115 char *get_op( pCodeOp *pcop);
116 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
117 int pCodePeepMatchRule(pCode *pc);
118 void pBlockStats(FILE *of, pBlock *pb);
119 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
120 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
121 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
123 pCodeInstruction pciADDWF = {
124 {PC_OPCODE, NULL, NULL, 0, NULL,
137 1,0, // dest, bit instruction
140 (PCC_W | PCC_REGISTER), // inCond
141 (PCC_REGISTER | PCC_Z) // outCond
144 pCodeInstruction pciADDFW = {
145 {PC_OPCODE, NULL, NULL, 0, NULL,
158 0,0, // dest, bit instruction
161 (PCC_W | PCC_REGISTER), // inCond
162 (PCC_W | PCC_Z) // outCond
165 pCodeInstruction pciADDLW = {
166 {PC_OPCODE, NULL, NULL, 0, NULL,
179 0,0, // dest, bit instruction
183 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
186 pCodeInstruction pciANDLW = {
187 {PC_OPCODE, NULL, NULL, 0, NULL,
200 0,0, // dest, bit instruction
204 (PCC_W | PCC_Z) // outCond
207 pCodeInstruction pciANDWF = {
208 {PC_OPCODE, NULL, NULL, 0, NULL,
221 1,0, // dest, bit instruction
224 (PCC_W | PCC_REGISTER), // inCond
225 (PCC_REGISTER | PCC_Z) // outCond
228 pCodeInstruction pciANDFW = {
229 {PC_OPCODE, NULL, NULL, 0, NULL,
242 0,0, // dest, bit instruction
245 (PCC_W | PCC_REGISTER), // inCond
246 (PCC_W | PCC_Z) // outCond
249 pCodeInstruction pciBCF = {
250 {PC_OPCODE, NULL, NULL, 0, NULL,
263 1,1, // dest, bit instruction
266 PCC_REGISTER, // inCond
267 PCC_REGISTER // outCond
270 pCodeInstruction pciBSF = {
271 {PC_OPCODE, NULL, NULL, 0, NULL,
284 1,1, // dest, bit instruction
287 PCC_REGISTER, // inCond
288 PCC_REGISTER // outCond
291 pCodeInstruction pciBTFSC = {
292 {PC_OPCODE, NULL, NULL, 0, NULL,
305 0,1, // dest, bit instruction
308 PCC_REGISTER, // inCond
312 pCodeInstruction pciBTFSS = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,1, // dest, bit instruction
329 PCC_REGISTER, // inCond
333 pCodeInstruction pciCALL = {
334 {PC_OPCODE, NULL, NULL, 0, NULL,
347 0,0, // dest, bit instruction
354 pCodeInstruction pciCOMF = {
355 {PC_OPCODE, NULL, NULL, 0, NULL,
368 1,0, // dest, bit instruction
371 PCC_REGISTER, // inCond
372 PCC_REGISTER // outCond
375 pCodeInstruction pciCOMFW = {
376 {PC_OPCODE, NULL, NULL, 0, NULL,
389 0,0, // dest, bit instruction
392 PCC_REGISTER, // inCond
396 pCodeInstruction pciCLRF = {
397 {PC_OPCODE, NULL, NULL, 0, NULL,
410 0,0, // dest, bit instruction
413 PCC_REGISTER, // inCond
414 PCC_REGISTER // outCond
417 pCodeInstruction pciCLRW = {
418 {PC_OPCODE, NULL, NULL, 0, NULL,
431 0,0, // dest, bit instruction
438 pCodeInstruction pciDECF = {
439 {PC_OPCODE, NULL, NULL, 0, NULL,
452 1,0, // dest, bit instruction
455 PCC_REGISTER, // inCond
456 PCC_REGISTER // outCond
459 pCodeInstruction pciDECFW = {
460 {PC_OPCODE, NULL, NULL, 0, NULL,
473 0,0, // dest, bit instruction
476 PCC_REGISTER, // inCond
480 pCodeInstruction pciDECFSZ = {
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 1,0, // dest, bit instruction
497 PCC_REGISTER, // inCond
498 PCC_REGISTER // outCond
501 pCodeInstruction pciDECFSZW = {
502 {PC_OPCODE, NULL, NULL, 0, NULL,
515 0,0, // dest, bit instruction
518 PCC_REGISTER, // inCond
522 pCodeInstruction pciGOTO = {
523 {PC_OPCODE, NULL, NULL, 0, NULL,
536 0,0, // dest, bit instruction
543 pCodeInstruction pciINCF = {
544 {PC_OPCODE, NULL, NULL, 0, NULL,
557 1,0, // dest, bit instruction
560 PCC_REGISTER, // inCond
561 PCC_REGISTER // outCond
564 pCodeInstruction pciINCFW = {
565 {PC_OPCODE, NULL, NULL, 0, NULL,
578 0,0, // dest, bit instruction
581 PCC_REGISTER, // inCond
585 pCodeInstruction pciINCFSZ = {
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 1,0, // dest, bit instruction
602 PCC_REGISTER, // inCond
603 PCC_REGISTER // outCond
606 pCodeInstruction pciINCFSZW = {
607 {PC_OPCODE, NULL, NULL, 0, NULL,
620 0,0, // dest, bit instruction
623 PCC_REGISTER, // inCond
627 pCodeInstruction pciIORWF = {
628 {PC_OPCODE, NULL, NULL, 0, NULL,
641 1,0, // dest, bit instruction
644 (PCC_W | PCC_REGISTER), // inCond
645 (PCC_REGISTER | PCC_Z) // outCond
648 pCodeInstruction pciIORFW = {
649 {PC_OPCODE, NULL, NULL, 0, NULL,
662 0,0, // dest, bit instruction
665 (PCC_W | PCC_REGISTER), // inCond
666 (PCC_W | PCC_Z) // outCond
669 pCodeInstruction pciIORLW = {
670 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,0, // dest, bit instruction
687 (PCC_W | PCC_Z) // outCond
690 pCodeInstruction pciMOVF = {
691 {PC_OPCODE, NULL, NULL, 0, NULL,
704 1,0, // dest, bit instruction
707 PCC_REGISTER, // inCond
711 pCodeInstruction pciMOVFW = {
712 {PC_OPCODE, NULL, NULL, 0, NULL,
725 0,0, // dest, bit instruction
728 PCC_REGISTER, // inCond
729 (PCC_W | PCC_Z) // outCond
732 pCodeInstruction pciMOVWF = {
733 {PC_OPCODE, NULL, NULL, 0, NULL,
746 0,0, // dest, bit instruction
750 PCC_REGISTER // outCond
753 pCodeInstruction pciMOVLW = {
754 {PC_OPCODE, NULL, NULL, 0, NULL,
767 0,0, // dest, bit instruction
774 pCodeInstruction pciNOP = {
775 {PC_OPCODE, NULL, NULL, 0, NULL,
787 0,0, // dest, bit instruction
794 pCodeInstruction pciRETFIE = {
795 {PC_OPCODE, NULL, NULL, 0, NULL,
808 0,0, // dest, bit instruction
812 PCC_NONE // outCond (not true... affects the GIE bit too)
815 pCodeInstruction pciRETLW = {
816 {PC_OPCODE, NULL, NULL, 0, NULL,
829 0,0, // dest, bit instruction
836 pCodeInstruction pciRETURN = {
837 {PC_OPCODE, NULL, NULL, 0, NULL,
850 0,0, // dest, bit instruction
857 pCodeInstruction pciRLF = {
858 {PC_OPCODE, NULL, NULL, 0, NULL,
871 1,0, // dest, bit instruction
874 (PCC_C | PCC_REGISTER), // inCond
875 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
878 pCodeInstruction pciRLFW = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
895 (PCC_C | PCC_REGISTER), // inCond
896 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
899 pCodeInstruction pciRRF = {
900 {PC_OPCODE, NULL, NULL, 0, NULL,
913 1,0, // dest, bit instruction
916 (PCC_C | PCC_REGISTER), // inCond
917 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
920 pCodeInstruction pciRRFW = {
921 {PC_OPCODE, NULL, NULL, 0, NULL,
934 0,0, // dest, bit instruction
937 (PCC_C | PCC_REGISTER), // inCond
938 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
941 pCodeInstruction pciSUBWF = {
942 {PC_OPCODE, NULL, NULL, 0, NULL,
955 1,0, // dest, bit instruction
958 (PCC_W | PCC_REGISTER), // inCond
959 (PCC_REGISTER | PCC_Z) // outCond
962 pCodeInstruction pciSUBFW = {
963 {PC_OPCODE, NULL, NULL, 0, NULL,
976 0,0, // dest, bit instruction
979 (PCC_W | PCC_REGISTER), // inCond
980 (PCC_W | PCC_Z) // outCond
983 pCodeInstruction pciSUBLW = {
984 {PC_OPCODE, NULL, NULL, 0, NULL,
997 0,0, // dest, bit instruction
1001 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1004 pCodeInstruction pciSWAPF = {
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 1,0, // dest, bit instruction
1019 0,0, // branch, skip
1021 (PCC_REGISTER), // inCond
1022 (PCC_REGISTER) // outCond
1025 pCodeInstruction pciSWAPFW = {
1026 {PC_OPCODE, NULL, NULL, 0, NULL,
1032 NULL, // from branch
1039 0,0, // dest, bit instruction
1040 0,0, // branch, skip
1042 (PCC_REGISTER), // inCond
1046 pCodeInstruction pciTRIS = {
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 0,0, // branch, skip
1064 PCC_REGISTER // outCond
1067 pCodeInstruction pciXORWF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1084 (PCC_W | PCC_REGISTER), // inCond
1085 (PCC_REGISTER | PCC_Z) // outCond
1088 pCodeInstruction pciXORFW = {
1089 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 0,0, // dest, bit instruction
1103 0,0, // branch, skip
1105 (PCC_W | PCC_REGISTER), // inCond
1106 (PCC_W | PCC_Z) // outCond
1109 pCodeInstruction pciXORLW = {
1110 {PC_OPCODE, NULL, NULL, 0, NULL,
1116 NULL, // from branch
1123 0,0, // dest, bit instruction
1124 0,0, // branch, skip
1127 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1131 #define MAX_PIC14MNEMONICS 100
1132 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1134 /* This definition needs to be part of configure.in */
1135 // #define USE_VSNPRINTF
1137 #ifdef USE_VSNPRINTF
1138 // Alas, vsnprintf is not ANSI standard, and does not exist
1139 // on Solaris (and probably other non-Gnu flavored Unixes).
1141 /*-----------------------------------------------------------------*/
1142 /* SAFE_snprintf - like snprintf except the string pointer is */
1143 /* after the string has been printed to. This is */
1144 /* useful for printing to string as though if it */
1145 /* were a stream. */
1146 /*-----------------------------------------------------------------*/
1147 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1155 va_start(val, format);
1157 vsnprintf(*str, *size, format, val);
1163 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1171 #else // USE_VSNPRINTF
1173 // This version is *not* safe, despite the name.
1175 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1179 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1184 va_start(val, format);
1186 vsprintf(buffer, format, val);
1189 len = strlen(buffer);
1191 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1194 strcpy(*str, buffer);
1200 #endif // USE_VSNPRINTF
1203 extern void initStack(int base_address, int size);
1204 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1205 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1206 extern void init_pic(char *);
1208 void pCodeInitRegisters(void)
1211 initStack(0xfff, 8);
1212 init_pic(port->processor);
1214 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1215 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1216 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1217 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1218 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1219 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1221 pc_status.rIdx = IDX_STATUS;
1222 pc_fsr.rIdx = IDX_FSR;
1223 pc_indf.rIdx = IDX_INDF;
1224 pc_intcon.rIdx = IDX_INTCON;
1225 pc_pcl.rIdx = IDX_PCL;
1226 pc_pclath.rIdx = IDX_PCLATH;
1228 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1229 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1230 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1232 pc_kzero.rIdx = IDX_KZ;
1233 pc_wsave.rIdx = IDX_WSAVE;
1234 pc_ssave.rIdx = IDX_SSAVE;
1238 /*-----------------------------------------------------------------*/
1239 /* mnem2key - convert a pic mnemonic into a hash key */
1240 /* (BTW - this spreads the mnemonics quite well) */
1242 /*-----------------------------------------------------------------*/
1244 int mnem2key(char const *mnem)
1253 key += toupper(*mnem++) +1;
1257 return (key & 0x1f);
1261 void pic14initMnemonics(void)
1266 pCodeInstruction *pci;
1268 if(mnemonics_initialized)
1271 //FIXME - probably should NULL out the array before making the assignments
1272 //since we check the array contents below this initialization.
1274 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1275 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1276 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1277 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1278 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1279 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1280 pic14Mnemonics[POC_BCF] = &pciBCF;
1281 pic14Mnemonics[POC_BSF] = &pciBSF;
1282 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1283 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1284 pic14Mnemonics[POC_CALL] = &pciCALL;
1285 pic14Mnemonics[POC_COMF] = &pciCOMF;
1286 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1287 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1288 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1289 pic14Mnemonics[POC_DECF] = &pciDECF;
1290 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1291 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1292 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1293 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1294 pic14Mnemonics[POC_INCF] = &pciINCF;
1295 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1296 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1297 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1298 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1299 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1300 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1301 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1302 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1303 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1304 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1305 pic14Mnemonics[POC_NOP] = &pciNOP;
1306 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1307 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1308 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1309 pic14Mnemonics[POC_RLF] = &pciRLF;
1310 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1311 pic14Mnemonics[POC_RRF] = &pciRRF;
1312 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1313 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1314 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1315 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1316 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1317 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1318 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1319 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1320 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1321 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1323 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1324 if(pic14Mnemonics[i])
1325 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1326 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1329 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1330 pci = hTabNextItem(pic14MnemonicsHash, &key);
1333 mnemonics_initialized = 1;
1336 int getpCodePeepCommand(char *cmd);
1338 int getpCode(char *mnem,unsigned dest)
1341 pCodeInstruction *pci;
1342 int key = mnem2key(mnem);
1344 if(!mnemonics_initialized)
1345 pic14initMnemonics();
1347 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1351 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1352 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1356 pci = hTabNextItemWK (pic14MnemonicsHash);
1363 /*-----------------------------------------------------------------*
1364 * pic14initpCodePeepCommands
1366 *-----------------------------------------------------------------*/
1367 void pic14initpCodePeepCommands(void)
1375 hTabAddItem(&pic14pCodePeepCommandsHash,
1376 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1378 } while (peepCommands[i].cmd);
1380 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1383 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1384 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1389 /*-----------------------------------------------------------------
1392 *-----------------------------------------------------------------*/
1394 int getpCodePeepCommand(char *cmd)
1398 int key = mnem2key(cmd);
1401 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1404 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1405 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1409 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1416 char getpBlock_dbName(pBlock *pb)
1422 return pb->cmemmap->dbName;
1426 void pBlockConvert2ISR(pBlock *pb)
1437 /*-----------------------------------------------------------------*/
1438 /* movepBlock2Head - given the dbname of a pBlock, move all */
1439 /* instances to the front of the doubly linked */
1440 /* list of pBlocks */
1441 /*-----------------------------------------------------------------*/
1443 void movepBlock2Head(char dbName)
1447 pb = the_pFile->pbHead;
1451 if(getpBlock_dbName(pb) == dbName) {
1452 pBlock *pbn = pb->next;
1453 pb->next = the_pFile->pbHead;
1454 the_pFile->pbHead->prev = pb;
1455 the_pFile->pbHead = pb;
1458 pb->prev->next = pbn;
1460 // If the pBlock that we just moved was the last
1461 // one in the link of all of the pBlocks, then we
1462 // need to point the tail to the block just before
1463 // the one we moved.
1464 // Note: if pb->next is NULL, then pb must have
1465 // been the last pBlock in the chain.
1468 pbn->prev = pb->prev;
1470 the_pFile->pbTail = pb->prev;
1481 void copypCode(FILE *of, char dbName)
1485 if(!of || !the_pFile)
1488 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1489 if(getpBlock_dbName(pb) == dbName) {
1496 void pcode_test(void)
1499 DFPRINTF((stderr,"pcode is alive!\n"));
1509 /* create the file name */
1510 strcpy(buffer,srcFileName);
1511 strcat(buffer,".p");
1513 if( !(pFile = fopen(buffer, "w" ))) {
1514 werror(E_FILE_OPEN_ERR,buffer);
1518 fprintf(pFile,"pcode dump\n\n");
1520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1521 fprintf(pFile,"\n\tNew pBlock\n\n");
1523 fprintf(pFile,"%s",pb->cmemmap->sname);
1525 fprintf(pFile,"internal pblock");
1527 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1528 printpBlock(pFile,pb);
1532 /*-----------------------------------------------------------------*/
1533 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1534 /* ister, RegCond will return the bit being referenced. */
1536 /* fixme - why not just OR in the pcop bit field */
1537 /*-----------------------------------------------------------------*/
1539 static int RegCond(pCodeOp *pcop)
1545 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1546 switch(PCORB(pcop)->bit) {
1560 /*-----------------------------------------------------------------*/
1561 /* newpCode - create and return a newly initialized pCode */
1563 /* fixme - rename this */
1565 /* The purpose of this routine is to create a new Instruction */
1566 /* pCode. This is called by gen.c while the assembly code is being */
1570 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1571 /* (note that the op is analogous to but not the */
1572 /* same thing as the opcode of the instruction.) */
1573 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1576 /* a pointer to the new malloc'd pCode is returned. */
1580 /*-----------------------------------------------------------------*/
1581 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1583 pCodeInstruction *pci ;
1585 if(!mnemonics_initialized)
1586 pic14initMnemonics();
1588 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1590 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1591 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1594 if(pci->inCond == PCC_EXAMINE_PCOP)
1595 pci->inCond = RegCond(pcop);
1597 if(pci->outCond == PCC_EXAMINE_PCOP)
1598 pci->outCond = RegCond(pcop);
1600 pci->pc.prev = pci->pc.next = NULL;
1601 return (pCode *)pci;
1604 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1610 /*-----------------------------------------------------------------*/
1611 /* newpCodeWild - create a "wild" as in wild card pCode */
1613 /* Wild pcodes are used during the peep hole optimizer to serve */
1614 /* as place holders for any instruction. When a snippet of code is */
1615 /* compared to a peep hole rule, the wild card opcode will match */
1616 /* any instruction. However, the optional operand and label are */
1617 /* additional qualifiers that must also be matched before the */
1618 /* line (of assembly code) is declared matched. Note that the */
1619 /* operand may be wild too. */
1621 /* Note, a wild instruction is specified just like a wild var: */
1622 /* %4 ; A wild instruction, */
1623 /* See the peeph.def file for additional examples */
1625 /*-----------------------------------------------------------------*/
1627 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1632 pcw = Safe_calloc(1,sizeof(pCodeWild));
1634 pcw->pci.pc.type = PC_WILD;
1635 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1636 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1637 pcw->pci.pc.pb = NULL;
1639 // pcw->pci.pc.analyze = genericAnalyze;
1640 pcw->pci.pc.destruct = genericDestruct;
1641 pcw->pci.pc.print = genericPrint;
1643 pcw->id = pCodeID; // this is the 'n' in %n
1644 pcw->operand = optional_operand;
1645 pcw->label = optional_label;
1647 pcw->mustBeBitSkipInst = 0;
1648 pcw->mustNotBeBitSkipInst = 0;
1649 pcw->invertBitSkipInst = 0;
1651 return ( (pCode *)pcw);
1655 /*-----------------------------------------------------------------*/
1656 /* newPcodeInlineP - create a new pCode from a char string */
1657 /*-----------------------------------------------------------------*/
1660 pCode *newpCodeInlineP(char *cP)
1665 pcc = Safe_calloc(1,sizeof(pCodeComment));
1667 pcc->pc.type = PC_INLINE;
1668 pcc->pc.prev = pcc->pc.next = NULL;
1669 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1672 // pcc->pc.analyze = genericAnalyze;
1673 pcc->pc.destruct = genericDestruct;
1674 pcc->pc.print = genericPrint;
1677 pcc->comment = Safe_strdup(cP);
1679 pcc->comment = NULL;
1681 return ( (pCode *)pcc);
1685 /*-----------------------------------------------------------------*/
1686 /* newPcodeCharP - create a new pCode from a char string */
1687 /*-----------------------------------------------------------------*/
1689 pCode *newpCodeCharP(char *cP)
1694 pcc = Safe_calloc(1,sizeof(pCodeComment));
1696 pcc->pc.type = PC_COMMENT;
1697 pcc->pc.prev = pcc->pc.next = NULL;
1698 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1701 // pcc->pc.analyze = genericAnalyze;
1702 pcc->pc.destruct = genericDestruct;
1703 pcc->pc.print = genericPrint;
1706 pcc->comment = Safe_strdup(cP);
1708 pcc->comment = NULL;
1710 return ( (pCode *)pcc);
1714 /*-----------------------------------------------------------------*/
1715 /* newpCodeFunction - */
1716 /*-----------------------------------------------------------------*/
1719 pCode *newpCodeFunction(char *mod,char *f)
1723 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1724 //_ALLOC(pcf,sizeof(pCodeFunction));
1726 pcf->pc.type = PC_FUNCTION;
1727 pcf->pc.prev = pcf->pc.next = NULL;
1728 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1731 // pcf->pc.analyze = genericAnalyze;
1732 pcf->pc.destruct = genericDestruct;
1733 pcf->pc.print = pCodePrintFunction;
1738 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1739 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1740 strcpy(pcf->modname,mod);
1742 pcf->modname = NULL;
1745 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1746 pcf->fname = Safe_calloc(1,strlen(f)+1);
1747 strcpy(pcf->fname,f);
1751 return ( (pCode *)pcf);
1755 /*-----------------------------------------------------------------*/
1757 /*-----------------------------------------------------------------*/
1759 void destructpCodeFlow(pCode *pc)
1761 if(!pc || !isPCFL(pc))
1765 free(PCFL(pc)->uses);
1773 pCode *newpCodeFlow(void )
1777 //_ALLOC(pcflow,sizeof(pCodeFlow));
1778 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1780 pcflow->pc.type = PC_FLOW;
1781 pcflow->pc.prev = pcflow->pc.next = NULL;
1782 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1783 pcflow->pc.pb = NULL;
1785 // pcflow->pc.analyze = genericAnalyze;
1786 pcflow->pc.destruct = destructpCodeFlow;
1787 pcflow->pc.print = genericPrint;
1789 pcflow->pc.seq = GpcFlowSeq++;
1792 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1794 pcflow->from = pcflow->to = NULL;
1796 pcflow->inCond = PCC_NONE;
1797 pcflow->outCond = PCC_NONE;
1799 pcflow->firstBank = -1;
1800 pcflow->lastBank = -1;
1802 pcflow->FromConflicts = 0;
1803 pcflow->ToConflicts = 0;
1806 return ( (pCode *)pcflow);
1810 /*-----------------------------------------------------------------*/
1811 /*-----------------------------------------------------------------*/
1812 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1814 pCodeFlowLink *pcflowLink;
1816 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1818 pcflowLink->pcflow = pcflow;
1819 pcflowLink->bank_conflict = 0;
1824 /*-----------------------------------------------------------------*/
1825 /* newpCodeCSource - create a new pCode Source Symbol */
1826 /*-----------------------------------------------------------------*/
1828 pCode *newpCodeCSource(int ln, char *f, char *l)
1833 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1835 pccs->pc.type = PC_CSOURCE;
1836 pccs->pc.prev = pccs->pc.next = NULL;
1839 pccs->pc.destruct = genericDestruct;
1840 pccs->pc.print = genericPrint;
1842 pccs->line_number = ln;
1844 pccs->line = Safe_strdup(l);
1849 pccs->file_name = Safe_strdup(f);
1851 pccs->file_name = NULL;
1853 return ( (pCode *)pccs);
1856 /*-----------------------------------------------------------------*/
1857 /* pCodeLabelDestruct - free memory used by a label. */
1858 /*-----------------------------------------------------------------*/
1859 static void pCodeLabelDestruct(pCode *pc)
1865 if((pc->type == PC_LABEL) && PCL(pc)->label)
1866 free(PCL(pc)->label);
1872 pCode *newpCodeLabel(char *name, int key)
1878 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1880 pcl->pc.type = PC_LABEL;
1881 pcl->pc.prev = pcl->pc.next = NULL;
1882 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1885 // pcl->pc.analyze = genericAnalyze;
1886 pcl->pc.destruct = pCodeLabelDestruct;
1887 pcl->pc.print = pCodePrintLabel;
1893 sprintf(s,"_%05d_DS_",key);
1898 pcl->label = Safe_strdup(s);
1901 return ( (pCode *)pcl);
1906 /*-----------------------------------------------------------------*/
1907 /* newpBlock - create and return a pointer to a new pBlock */
1908 /*-----------------------------------------------------------------*/
1909 pBlock *newpBlock(void)
1914 PpB = Safe_calloc(1,sizeof(pBlock) );
1915 PpB->next = PpB->prev = NULL;
1917 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1918 PpB->tregisters = NULL;
1925 /*-----------------------------------------------------------------*/
1926 /* newpCodeChain - create a new chain of pCodes */
1927 /*-----------------------------------------------------------------*
1929 * This function will create a new pBlock and the pointer to the
1930 * pCode that is passed in will be the first pCode in the block.
1931 *-----------------------------------------------------------------*/
1934 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1937 pBlock *pB = newpBlock();
1939 pB->pcHead = pB->pcTail = pc;
1946 /*-----------------------------------------------------------------*/
1947 /* newpCodeOpLabel - Create a new label given the key */
1948 /* Note, a negative key means that the label is part of wild card */
1949 /* (and hence a wild card label) used in the pCodePeep */
1950 /* optimizations). */
1951 /*-----------------------------------------------------------------*/
1953 pCodeOp *newpCodeOpLabel(char *name, int key)
1956 static int label_key=-1;
1960 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1961 pcop->type = PO_LABEL;
1966 sprintf(s=buffer,"_%05d_DS_",key);
1968 s = name, key = label_key--;
1971 pcop->name = Safe_strdup(s);
1973 ((pCodeOpLabel *)pcop)->key = key;
1978 /*-----------------------------------------------------------------*/
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *newpCodeOpLit(int lit)
1986 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1987 pcop->type = PO_LITERAL;
1991 sprintf(s,"0x%02x",lit);
1993 pcop->name = Safe_strdup(s);
1996 ((pCodeOpLit *)pcop)->lit = lit;
2001 /*-----------------------------------------------------------------*/
2002 /*-----------------------------------------------------------------*/
2003 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2007 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2008 pcop->type = PO_IMMEDIATE;
2010 pcop->name = Safe_strdup(name);
2011 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2017 PCOI(pcop)->index = index;
2018 PCOI(pcop)->offset = offset;
2019 PCOI(pcop)->_const = code_space;
2024 /*-----------------------------------------------------------------*/
2025 /*-----------------------------------------------------------------*/
2026 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2032 if(!pcwb || !subtype) {
2033 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2037 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2038 pcop->type = PO_WILD;
2039 sprintf(s,"%%%d",id);
2040 pcop->name = Safe_strdup(s);
2042 PCOW(pcop)->id = id;
2043 PCOW(pcop)->pcwb = pcwb;
2044 PCOW(pcop)->subtype = subtype;
2045 PCOW(pcop)->matched = NULL;
2050 /*-----------------------------------------------------------------*/
2051 /*-----------------------------------------------------------------*/
2052 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2056 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2057 pcop->type = PO_GPR_BIT;
2059 pcop->name = Safe_strdup(s);
2063 PCORB(pcop)->bit = bit;
2064 PCORB(pcop)->inBitSpace = inBitSpace;
2069 /*-----------------------------------------------------------------*
2070 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2072 * If rIdx >=0 then a specific register from the set of registers
2073 * will be selected. If rIdx <0, then a new register will be searched
2075 *-----------------------------------------------------------------*/
2077 pCodeOp *newpCodeOpReg(int rIdx)
2081 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2086 PCOR(pcop)->rIdx = rIdx;
2087 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2089 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2092 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2093 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2096 pcop->type = PCOR(pcop)->r->pc_type;
2101 pCodeOp *newpCodeOpRegFromStr(char *name)
2105 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106 PCOR(pcop)->r = allocRegByName(name, 1);
2107 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108 pcop->type = PCOR(pcop)->r->pc_type;
2109 pcop->name = PCOR(pcop)->r->name;
2114 /*-----------------------------------------------------------------*/
2115 /*-----------------------------------------------------------------*/
2117 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2124 pcop = newpCodeOpBit(name, -1,0);
2128 pcop = newpCodeOpLit(-1);
2132 pcop = newpCodeOpLabel(NULL,-1);
2135 pcop = newpCodeOpReg(-1);
2139 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2142 pcop->name = Safe_strdup(name);
2150 /*-----------------------------------------------------------------*/
2151 /*-----------------------------------------------------------------*/
2152 void pCodeConstString(char *name, char *value)
2156 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2161 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2165 sprintf(buffer,"; %s = %s",name,value);
2167 addpCode2pBlock(pb,newpCodeCharP(buffer));
2168 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2171 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2177 /*-----------------------------------------------------------------*/
2178 /*-----------------------------------------------------------------*/
2179 void pCodeReadCodeTable(void)
2183 fprintf(stderr, " %s\n",__FUNCTION__);
2185 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2189 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2190 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2191 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2192 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2194 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2195 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2196 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2197 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2202 /*-----------------------------------------------------------------*/
2203 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2204 /*-----------------------------------------------------------------*/
2205 void addpCode2pBlock(pBlock *pb, pCode *pc)
2208 /* If this is the first pcode to be added to a block that
2209 * was initialized with a NULL pcode, then go ahead and
2210 * make this pcode the head and tail */
2211 pb->pcHead = pb->pcTail = pc;
2213 pb->pcTail->next = pc;
2214 pc->prev = pb->pcTail;
2221 /*-----------------------------------------------------------------*/
2222 /* addpBlock - place a pBlock into the pFile */
2223 /*-----------------------------------------------------------------*/
2224 void addpBlock(pBlock *pb)
2226 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2229 /* First time called, we'll pass through here. */
2230 //_ALLOC(the_pFile,sizeof(pFile));
2231 the_pFile = Safe_calloc(1,sizeof(pFile));
2232 the_pFile->pbHead = the_pFile->pbTail = pb;
2233 the_pFile->functions = NULL;
2237 the_pFile->pbTail->next = pb;
2238 pb->prev = the_pFile->pbTail;
2240 the_pFile->pbTail = pb;
2243 /*-----------------------------------------------------------------*/
2244 /* removepBlock - remove a pBlock from the pFile */
2245 /*-----------------------------------------------------------------*/
2246 void removepBlock(pBlock *pb)
2254 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2256 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2259 if(pbs == the_pFile->pbHead)
2260 the_pFile->pbHead = pbs->next;
2262 if (pbs == the_pFile->pbTail)
2263 the_pFile->pbTail = pbs->prev;
2266 pbs->next->prev = pbs->prev;
2269 pbs->prev->next = pbs->next;
2276 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2280 /*-----------------------------------------------------------------*/
2281 /* printpCode - write the contents of a pCode to a file */
2282 /*-----------------------------------------------------------------*/
2283 void printpCode(FILE *of, pCode *pc)
2294 fprintf(of,"warning - unable to print pCode\n");
2297 /*-----------------------------------------------------------------*/
2298 /* printpBlock - write the contents of a pBlock to a file */
2299 /*-----------------------------------------------------------------*/
2300 void printpBlock(FILE *of, pBlock *pb)
2310 for(pc = pb->pcHead; pc; pc = pc->next)
2315 /*-----------------------------------------------------------------*/
2317 /* pCode processing */
2321 /*-----------------------------------------------------------------*/
2323 static void unlinkPC(pCode *pc)
2329 fprintf(stderr,"Unlinking: ");
2330 printpCode(stderr, pc);
2333 pc->prev->next = pc->next;
2335 pc->next->prev = pc->prev;
2337 pc->prev = pc->next = NULL;
2340 static void genericDestruct(pCode *pc)
2342 //fprintf(stderr,"warning, calling default pCode destructor\n");
2351 /*-----------------------------------------------------------------*/
2352 /*-----------------------------------------------------------------*/
2353 void pBlockRegs(FILE *of, pBlock *pb)
2358 r = setFirstItem(pb->tregisters);
2360 r = setNextItem(pb->tregisters);
2365 /*-----------------------------------------------------------------*/
2366 /*-----------------------------------------------------------------*/
2367 char *get_op(pCodeOp *pcop)
2370 static char buffer[50];
2376 switch(pcop->type) {
2379 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2380 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2382 return PCOR(pcop)->r->name;
2385 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2386 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2390 // return PCOR(pcc->pcop)->r)->name;
2393 size = sizeof(buffer);
2394 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2395 if(PCOI(pcop)->_const) {
2397 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2398 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2401 8 * PCOI(pcop)->offset );
2403 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2406 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2407 SAFE_snprintf(&s,&size,"(%s + %d)",
2409 PCOI(pcop)->index );
2411 SAFE_snprintf(&s,&size,"%s",pcop->name);
2418 size = sizeof(buffer);
2419 if( PCOR(pcop)->instance) {
2420 SAFE_snprintf(&s,&size,"(%s + %d)",
2422 PCOR(pcop)->instance );
2423 //fprintf(stderr,"PO_DIR %s\n",buffer);
2425 SAFE_snprintf(&s,&size,"%s",pcop->name);
2435 return "NO operand";
2439 /*-----------------------------------------------------------------*/
2440 /*-----------------------------------------------------------------*/
2441 static char *get_op_from_instruction( pCodeInstruction *pcc)
2445 return get_op(pcc->pcop);
2447 return ("ERROR Null: "__FUNCTION__);
2451 /*-----------------------------------------------------------------*/
2452 /*-----------------------------------------------------------------*/
2453 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2456 fprintf(of,"pcodeopprint- not implemented\n");
2459 /*-----------------------------------------------------------------*/
2460 /*-----------------------------------------------------------------*/
2461 char *pCode2str(char *str, int size, pCode *pc)
2469 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2471 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2473 if(PCI(pc)->isBitInst) {
2474 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2475 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2476 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2477 PCI(pc)->pcop->name ,
2478 PCI(pc)->pcop->name );
2480 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2481 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2482 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2483 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2485 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2486 //PCI(pc)->pcop->t.bit );
2489 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2490 if( PCI(pc)->num_ops == 2)
2491 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2493 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2496 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2498 if( PCI(pc)->num_ops == 2)
2499 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2507 /* assuming that comment ends with a \n */
2508 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2512 /* assuming that inline code ends with a \n */
2513 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2517 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2520 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2523 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2526 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2529 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2538 /*-----------------------------------------------------------------*/
2539 /* genericPrint - the contents of a pCode to a file */
2540 /*-----------------------------------------------------------------*/
2541 static void genericPrint(FILE *of, pCode *pc)
2549 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2553 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2557 // If the opcode has a label, print that first
2559 pBranch *pbl = PCI(pc)->label;
2560 while(pbl && pbl->pc) {
2561 if(pbl->pc->type == PC_LABEL)
2562 pCodePrintLabel(of, pbl->pc);
2568 genericPrint(of,PCODE(PCI(pc)->cline));
2573 pCode2str(str, 256, pc);
2575 fprintf(of,"%s",str);
2578 fprintf(of, "\t;key=%03x",pc->seq);
2580 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2584 pBranch *dpb = pc->to; // debug
2586 switch ( dpb->pc->type) {
2588 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2591 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2594 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2597 fprintf(of, "\t;flow");
2611 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2612 if(PCW(pc)->pci.label)
2613 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2615 if(PCW(pc)->operand) {
2616 fprintf(of,";\toperand ");
2617 pCodeOpPrint(of,PCW(pc)->operand );
2622 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2626 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2630 fprintf(of,"unknown pCode type %d\n",pc->type);
2635 /*-----------------------------------------------------------------*/
2636 /* pCodePrintFunction - prints function begin/end */
2637 /*-----------------------------------------------------------------*/
2639 static void pCodePrintFunction(FILE *of, pCode *pc)
2645 if( ((pCodeFunction *)pc)->modname)
2646 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2648 if(PCF(pc)->fname) {
2649 pBranch *exits = PCF(pc)->to;
2651 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2654 exits = exits->next;
2657 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2660 if((PCF(pc)->from &&
2661 PCF(pc)->from->pc->type == PC_FUNCTION &&
2662 PCF(PCF(pc)->from->pc)->fname) )
2663 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2665 fprintf(of,"; exit point [can't find entry point]\n");
2668 /*-----------------------------------------------------------------*/
2669 /* pCodePrintLabel - prints label */
2670 /*-----------------------------------------------------------------*/
2672 static void pCodePrintLabel(FILE *of, pCode *pc)
2679 fprintf(of,"%s\n",PCL(pc)->label);
2680 else if (PCL(pc)->key >=0)
2681 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2683 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2686 /*-----------------------------------------------------------------*/
2687 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2688 /* remove it if it is found. */
2689 /*-----------------------------------------------------------------*/
2690 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2697 if(pcl->type == PC_OPCODE)
2698 b = PCI(pcl)->label;
2700 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2705 //fprintf (stderr, "%s \n",__FUNCTION__);
2706 //pcl->print(stderr,pcl);
2707 //pc->print(stderr,pc);
2710 //fprintf (stderr, "found label\n");
2714 bprev->next = b->next; /* Not first pCode in chain */
2718 PCI(pcl)->label = b->next; /* First pCode in chain */
2721 return; /* A label can't occur more than once */
2729 /*-----------------------------------------------------------------*/
2730 /*-----------------------------------------------------------------*/
2731 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2747 /*-----------------------------------------------------------------*/
2748 /* pBranchLink - given two pcodes, this function will link them */
2749 /* together through their pBranches */
2750 /*-----------------------------------------------------------------*/
2751 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2755 // Declare a new branch object for the 'from' pCode.
2757 //_ALLOC(b,sizeof(pBranch));
2758 b = Safe_calloc(1,sizeof(pBranch));
2759 b->pc = PCODE(t); // The link to the 'to' pCode.
2762 f->to = pBranchAppend(f->to,b);
2764 // Now do the same for the 'to' pCode.
2766 //_ALLOC(b,sizeof(pBranch));
2767 b = Safe_calloc(1,sizeof(pBranch));
2771 t->from = pBranchAppend(t->from,b);
2776 /*-----------------------------------------------------------------*/
2777 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2779 /*-----------------------------------------------------------------*/
2780 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2793 /*-----------------------------------------------------------------*/
2794 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2795 /*-----------------------------------------------------------------*/
2796 static void pCodeUnlink(pCode *pc)
2801 if(!pc->prev || !pc->next) {
2802 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2806 /* first remove the pCode from the chain */
2807 pc->prev->next = pc->next;
2808 pc->next->prev = pc->prev;
2810 /* Now for the hard part... */
2812 /* Remove the branches */
2816 pc1 = pb1->pc; /* Get the pCode that branches to the
2817 * one we're unlinking */
2819 /* search for the link back to this pCode (the one we're
2821 if(pb2 = pBranchFind(pc1->to,pc)) {
2822 pb2->pc = pc->to->pc; // make the replacement
2824 /* if the pCode we're unlinking contains multiple 'to'
2825 * branches (e.g. this a skip instruction) then we need
2826 * to copy these extra branches to the chain. */
2828 pBranchAppend(pb2, pc->to->next);
2837 /*-----------------------------------------------------------------*/
2838 /*-----------------------------------------------------------------*/
2840 static void genericAnalyze(pCode *pc)
2850 // Go through the pCodes that are in pCode chain and link
2851 // them together through the pBranches. Note, the pCodes
2852 // are linked together as a contiguous stream like the
2853 // assembly source code lines. The linking here mimics this
2854 // except that comments are not linked in.
2856 pCode *npc = pc->next;
2858 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2859 pBranchLink(pc,npc);
2864 /* reached the end of the pcode chain without finding
2865 * an instruction we could link to. */
2869 fprintf(stderr,"analyze PC_FLOW\n");
2876 /*-----------------------------------------------------------------*/
2877 /*-----------------------------------------------------------------*/
2878 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2882 if(pc->type == PC_LABEL) {
2883 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2886 if(pc->type == PC_OPCODE) {
2887 pbr = PCI(pc)->label;
2889 if(pbr->pc->type == PC_LABEL) {
2890 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2900 /*-----------------------------------------------------------------*/
2901 /*-----------------------------------------------------------------*/
2902 int checkLabel(pCode *pc)
2906 if(pc && isPCI(pc)) {
2907 pbr = PCI(pc)->label;
2909 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2919 /*-----------------------------------------------------------------*/
2920 /* findLabelinpBlock - Search the pCode for a particular label */
2921 /*-----------------------------------------------------------------*/
2922 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2929 for(pc = pb->pcHead; pc; pc = pc->next)
2930 if(compareLabel(pc,pcop_label))
2936 /*-----------------------------------------------------------------*/
2937 /* findLabel - Search the pCode for a particular label */
2938 /*-----------------------------------------------------------------*/
2939 pCode * findLabel(pCodeOpLabel *pcop_label)
2947 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2948 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2952 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2956 /*-----------------------------------------------------------------*/
2957 /* findNextpCode - given a pCode, find the next of type 'pct' */
2958 /* in the linked list */
2959 /*-----------------------------------------------------------------*/
2960 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2973 /*-----------------------------------------------------------------*/
2974 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2975 /* in the linked list */
2976 /*-----------------------------------------------------------------*/
2977 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2989 /*-----------------------------------------------------------------*/
2990 /* findNextInstruction - given a pCode, find the next instruction */
2991 /* in the linked list */
2992 /*-----------------------------------------------------------------*/
2993 pCode * findNextInstruction(pCode *pci)
2998 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3002 fprintf(stderr,"findNextInstruction: ");
3003 printpCode(stderr, pc);
3008 //fprintf(stderr,"Couldn't find instruction\n");
3012 /*-----------------------------------------------------------------*/
3013 /* findNextInstruction - given a pCode, find the next instruction */
3014 /* in the linked list */
3015 /*-----------------------------------------------------------------*/
3016 pCode * findPrevInstruction(pCode *pci)
3018 return findPrevpCode(pci, PC_OPCODE);
3021 /*-----------------------------------------------------------------*/
3022 /* findFunctionEnd - given a pCode find the end of the function */
3023 /* that contains it */
3024 /*-----------------------------------------------------------------*/
3025 pCode * findFunctionEnd(pCode *pc)
3029 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3035 fprintf(stderr,"Couldn't find function end\n");
3040 /*-----------------------------------------------------------------*/
3041 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3042 /* instruction with which it is associated. */
3043 /*-----------------------------------------------------------------*/
3044 static void AnalyzeLabel(pCode *pc)
3053 static void AnalyzeGOTO(pCode *pc)
3056 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3060 static void AnalyzeSKIP(pCode *pc)
3063 pBranchLink(pc,findNextInstruction(pc->next));
3064 pBranchLink(pc,findNextInstruction(pc->next->next));
3068 static void AnalyzeRETURN(pCode *pc)
3071 // branch_link(pc,findFunctionEnd(pc->next));
3077 /*-----------------------------------------------------------------*/
3078 /*-----------------------------------------------------------------*/
3079 regs * getRegFromInstruction(pCode *pc)
3084 PCI(pc)->num_ops == 0 )
3087 switch(PCI(pc)->pcop->type) {
3090 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3094 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3095 return PCOR(PCI(pc)->pcop)->r;
3098 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3099 return NULL; // PCOR(PCI(pc)->pcop)->r;
3102 return PCOR(PCI(pc)->pcop)->r;
3105 //fprintf(stderr, "getRegFromInstruction - dir\n");
3106 return PCOR(PCI(pc)->pcop)->r;
3108 //fprintf(stderr, "getRegFromInstruction - literal\n");
3112 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3113 //genericPrint(stderr, pc);
3121 /*-----------------------------------------------------------------*/
3122 /*-----------------------------------------------------------------*/
3124 void AnalyzepBlock(pBlock *pb)
3131 /* Find all of the registers used in this pBlock
3132 * by looking at each instruction and examining it's
3135 for(pc = pb->pcHead; pc; pc = pc->next) {
3137 /* Is this an instruction with operands? */
3138 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3140 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3142 /* Loop through all of the registers declared so far in
3143 this block and see if we find this one there */
3145 regs *r = setFirstItem(pb->tregisters);
3148 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3149 PCOR(PCI(pc)->pcop)->r = r;
3152 r = setNextItem(pb->tregisters);
3156 /* register wasn't found */
3157 r = Safe_calloc(1, sizeof(regs));
3158 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3159 addSet(&pb->tregisters, r);
3160 PCOR(PCI(pc)->pcop)->r = r;
3161 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3163 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3166 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3167 if(PCOR(PCI(pc)->pcop)->r) {
3168 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3169 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3171 if(PCI(pc)->pcop->name)
3172 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3174 fprintf(stderr,"ERROR: NULL register\n");
3183 /*-----------------------------------------------------------------*/
3185 /*-----------------------------------------------------------------*/
3186 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3188 void InsertpFlow(pCode *pc, pCode **pflow)
3190 PCFL(*pflow)->end = pc;
3192 if(!pc || !pc->next)
3195 *pflow = newpCodeFlow();
3196 pCodeInsertAfter(pc, *pflow);
3199 /*-----------------------------------------------------------------*/
3200 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3201 /* the flow blocks. */
3203 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3204 * point the instruction flow changes.
3206 /*-----------------------------------------------------------------*/
3207 void BuildFlow(pBlock *pb)
3210 pCode *last_pci=NULL;
3217 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3218 /* Insert a pCodeFlow object at the beginning of a pBlock */
3220 pflow = newpCodeFlow(); /* Create a new Flow object */
3221 pflow->next = pb->pcHead; /* Make the current head the next object */
3222 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3223 pb->pcHead = pflow; /* Make the Flow object the head */
3226 for( pc = findNextInstruction(pb->pcHead);
3228 pc=findNextInstruction(pc)) {
3231 PCI(pc)->pcflow = PCFL(pflow);
3233 //fprintf(stderr," build: ");
3234 //pflow->print(stderr,pflow);
3236 if( PCI(pc)->isSkip) {
3238 /* The two instructions immediately following this one
3239 * mark the beginning of a new flow segment */
3241 while(pc && PCI(pc)->isSkip) {
3243 PCI(pc)->pcflow = PCFL(pflow);
3247 InsertpFlow(pc, &pflow);
3248 pc=findNextInstruction(pc->next);
3256 PCI(pc)->pcflow = PCFL(pflow);
3258 InsertpFlow(pc, &pflow);
3260 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3262 InsertpFlow(pc, &pflow);
3265 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3267 /* This instruction marks the beginning of a
3268 * new flow segment */
3272 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3274 PCI(pc)->pcflow = PCFL(pflow);
3281 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3282 PCFL(pflow)->end = pb->pcTail;
3285 /*-------------------------------------------------------------------*/
3286 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3287 /* the flow blocks. */
3289 * unBuildFlow removes pCodeFlow objects from a pCode chain
3291 /*-----------------------------------------------------------------*/
3292 void unBuildFlow(pBlock *pb)
3301 pCode *pcn = pc->next;
3305 PCI(pc)->pcflow = NULL;
3307 } else if(isPCFL(pc)) {
3317 /*-----------------------------------------------------------------*/
3318 /*-----------------------------------------------------------------*/
3319 void dumpCond(int cond)
3322 static char *pcc_str[] = {
3336 int ncond = sizeof(pcc_str) / sizeof(char *);
3339 fprintf(stderr, "0x%04X\n",cond);
3341 for(i=0,j=1; i<ncond; i++, j<<=1)
3343 fprintf(stderr, " %s\n",pcc_str[i]);
3347 /*-----------------------------------------------------------------*/
3348 /*-----------------------------------------------------------------*/
3349 void FlowStats(pCodeFlow *pcflow)
3357 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3359 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3362 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3367 fprintf(stderr, " FlowStats inCond: ");
3368 dumpCond(pcflow->inCond);
3369 fprintf(stderr, " FlowStats outCond: ");
3370 dumpCond(pcflow->outCond);
3374 /*-----------------------------------------------------------------*
3375 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3376 * if it affects the banking bits.
3378 * return: -1 == Banking bits are unaffected by this pCode.
3380 * return: > 0 == Banking bits are affected.
3382 * If the banking bits are affected, then the returned value describes
3383 * which bits are affected and how they're affected. The lower half
3384 * of the integer maps to the bits that are affected, the upper half
3385 * to whether they're set or cleared.
3387 *-----------------------------------------------------------------*/
3388 #define SET_BANK_BIT (1 << 16)
3389 #define CLR_BANK_BIT 0
3391 int isBankInstruction(pCode *pc)
3399 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3401 /* Check to see if the register banks are changing */
3402 if(PCI(pc)->isModReg) {
3404 pCodeOp *pcop = PCI(pc)->pcop;
3405 switch(PCI(pc)->op) {
3408 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3409 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3410 return SET_BANK_BIT | PIC_RP0_BIT;
3413 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3414 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3415 return CLR_BANK_BIT | PIC_RP0_BIT;
3420 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3421 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3422 return CLR_BANK_BIT | PIC_RP1_BIT;
3424 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3425 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3426 return CLR_BANK_BIT | PIC_RP1_BIT;
3430 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3431 //genericPrint(stderr, pc);
3442 /*-----------------------------------------------------------------*/
3443 /*-----------------------------------------------------------------*/
3444 void FillFlow(pCodeFlow *pcflow)
3453 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3455 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3458 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3465 isBankInstruction(pc);
3467 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3471 fprintf(stderr, " FillFlow - Bad end of flow\n");
3473 fprintf(stderr, " FillFlow - Ending flow with\n ");
3474 pc->print(stderr,pc);
3477 fprintf(stderr, " FillFlow inCond: ");
3478 dumpCond(pcflow->inCond);
3479 fprintf(stderr, " FillFlow outCond: ");
3480 dumpCond(pcflow->outCond);
3484 /*-----------------------------------------------------------------*/
3485 /*-----------------------------------------------------------------*/
3486 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3488 pCodeFlowLink *fromLink, *toLink;
3490 if(!from || !to || !to->pcflow || !from->pcflow)
3493 fromLink = newpCodeFlowLink(from->pcflow);
3494 toLink = newpCodeFlowLink(to->pcflow);
3496 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3497 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3501 /*-----------------------------------------------------------------*/
3502 /*-----------------------------------------------------------------*/
3503 void LinkFlow(pBlock *pb)
3509 //fprintf(stderr,"linkflow \n");
3511 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3513 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3516 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3518 //fprintf(stderr," link: ");
3519 //pcflow->print(stderr,pcflow);
3521 //FillFlow(PCFL(pcflow));
3523 pc = PCFL(pcflow)->end;
3525 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3526 if(isPCI_SKIP(pc)) {
3527 //fprintf(stderr, "ends with skip\n");
3528 //pc->print(stderr,pc);
3529 pct=findNextInstruction(pc->next);
3530 LinkFlow_pCode(PCI(pc),PCI(pct));
3531 pct=findNextInstruction(pct->next);
3532 LinkFlow_pCode(PCI(pc),PCI(pct));
3536 if(isPCI_BRANCH(pc)) {
3537 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3539 //fprintf(stderr, "ends with branch\n ");
3540 //pc->print(stderr,pc);
3542 if(!(pcol && isPCOLAB(pcol))) {
3543 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3544 pc->print(stderr,pc);
3545 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3550 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3551 LinkFlow_pCode(PCI(pc),PCI(pct));
3553 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3559 //fprintf(stderr, "ends with non-branching instruction:\n");
3560 //pc->print(stderr,pc);
3562 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3568 //fprintf(stderr, "ends with unknown\n");
3569 //pc->print(stderr,pc);
3573 //fprintf(stderr, "ends with nothing: ERROR\n");
3578 /*-----------------------------------------------------------------*/
3579 /*-----------------------------------------------------------------*/
3580 int isPCinFlow(pCode *pc, pCode *pcflow)
3586 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3589 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3595 /*-----------------------------------------------------------------*/
3596 /*-----------------------------------------------------------------*/
3597 void BanksUsedFlow2(pCode *pcflow)
3606 if(!isPCFL(pcflow)) {
3607 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3611 pc = findNextInstruction(pcflow->next);
3613 PCFL(pcflow)->lastBank = -1;
3615 while(isPCinFlow(pc,pcflow)) {
3617 int bank_selected = isBankInstruction(pc);
3619 //if(PCI(pc)->pcflow)
3620 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3622 if(bank_selected > 0) {
3623 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3625 /* This instruction is modifying banking bits before accessing registers */
3627 PCFL(pcflow)->firstBank = -1;
3629 if(PCFL(pcflow)->lastBank == -1)
3630 PCFL(pcflow)->lastBank = 0;
3632 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3633 if(bank_selected & SET_BANK_BIT)
3634 PCFL(pcflow)->lastBank |= bank;
3638 reg = getRegFromInstruction(pc);
3640 if(reg && !isREGinBank(reg, bank)) {
3641 int allbanks = REGallBanks(reg);
3643 PCFL(pcflow)->firstBank = allbanks;
3645 PCFL(pcflow)->lastBank = allbanks;
3652 pc = findNextInstruction(pc->next);
3655 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3656 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3661 /*-----------------------------------------------------------------*/
3662 /*-----------------------------------------------------------------*/
3663 void BanksUsedFlow(pBlock *pb)
3668 //pb->pcHead->print(stderr, pb->pcHead);
3670 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3671 //pcflow->print(stderr,pcflow);
3673 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3675 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3677 BanksUsedFlow2(pcflow);
3683 /*-----------------------------------------------------------------*/
3684 /*-----------------------------------------------------------------*/
3685 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3693 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3695 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3696 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3698 pCodeInsertAfter(pc->prev, new_pc);
3700 /* Move the label, if there is one */
3702 if(PCI(pc)->label) {
3703 PCI(new_pc)->label = PCI(pc)->label;
3704 PCI(pc)->label = NULL;
3707 /* The new instruction has the same pcflow block */
3708 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3713 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3724 pc = findNextInstruction(pcfl->pc.next);
3726 while(isPCinFlow(pc,PCODE(pcfl))) {
3729 reg = getRegFromInstruction(pc);
3732 fprintf(stderr, " %s ",reg->name);
3733 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3738 if(reg && REG_BANK(reg)!=cur_bank) {
3739 /* Examine the instruction before this one to make sure it is
3740 * not a skip type instruction */
3741 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3742 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3743 int b = cur_bank ^ REG_BANK(reg);
3745 //fprintf(stderr, "Cool! can switch banks\n");
3746 cur_bank = REG_BANK(reg);
3751 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3754 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3755 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3759 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3760 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3762 insertBankSwitch(pc, -1, -1);
3765 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3766 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3767 pCodeInsertAfter(pc->prev, new_pc);
3768 if(PCI(pc)->label) {
3769 PCI(new_pc)->label = PCI(pc)->label;
3770 PCI(pc)->label = NULL;
3774 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3775 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3776 pCodeInsertAfter(pc, new_pc);
3782 //fprintf(stderr, "Bummer can't switch banks\n");
3788 pc = findNextInstruction(pc->next);
3792 if(pcprev && cur_bank) {
3793 /* Brute force - make sure that we point to bank 0 at the
3794 * end of each flow block */
3795 new_pc = newpCode(POC_BCF,
3796 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3797 pCodeInsertAfter(pcprev, new_pc);
3803 /*-----------------------------------------------------------------*/
3804 /*int compareBankFlow - compare the banking requirements between */
3806 /*-----------------------------------------------------------------*/
3807 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3810 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3813 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3816 if(pcflow->firstBank == -1)
3820 if(pcflowLink->pcflow->firstBank == -1) {
3821 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3822 pcflowLink->pcflow->to :
3823 pcflowLink->pcflow->from);
3824 return compareBankFlow(pcflow, pctl, toORfrom);
3828 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3831 pcflowLink->bank_conflict++;
3832 pcflowLink->pcflow->FromConflicts++;
3833 pcflow->ToConflicts++;
3836 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3839 pcflowLink->bank_conflict++;
3840 pcflowLink->pcflow->ToConflicts++;
3841 pcflow->FromConflicts++;
3845 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3846 pcflowLink->pcflow->pc.seq,
3847 pcflowLink->pcflow->FromConflicts,
3848 pcflowLink->pcflow->ToConflicts);
3853 /*-----------------------------------------------------------------*/
3854 /*-----------------------------------------------------------------*/
3855 void FixBankFlow(pBlock *pb)
3859 pCodeFlowLink *pcfl;
3861 pCode *pcflow_max_To=NULL;
3862 pCode *pcflow_max_From=NULL;
3863 int max_ToConflicts=0;
3864 int max_FromConflicts=0;
3866 //fprintf(stderr,"Fix Bank flow \n");
3867 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3871 First loop through all of the flow objects in this pcode block
3872 and fix the ones that have banking conflicts between the
3876 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3878 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3880 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3882 if(!isPCFL(pcflow)) {
3883 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3887 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3888 PCFL(pcflow)->firstBank >= 0 &&
3889 PCFL(pcflow)->lastBank >= 0 ) {
3891 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3892 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3894 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3895 BanksUsedFlow2(pcflow);
3900 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3902 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3904 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3909 if(!isPCFL(pcflow)) {
3910 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3914 PCFL(pcflow)->FromConflicts = 0;
3915 PCFL(pcflow)->ToConflicts = 0;
3920 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3921 pcfl = setFirstItem(PCFL(pcflow)->from);
3924 pc = PCODE(pcfl->pcflow);
3927 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3928 pc->print(stderr,pc);
3931 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3934 pcfl=setNextItem(PCFL(pcflow)->from);
3937 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3938 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3940 FixRegisterBankingInFlow(PCFL(pcflow),0);
3941 BanksUsedFlow2(pcflow);
3943 continue; /* Don't need to check the flow from here - it's already been fixed */
3950 pcfl = setFirstItem(PCFL(pcflow)->to);
3953 pc = PCODE(pcfl->pcflow);
3955 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3956 pc->print(stderr,pc);
3959 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
3962 pcfl=setNextItem(PCFL(pcflow)->to);
3965 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
3966 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3968 FixRegisterBankingInFlow(PCFL(pcflow),0);
3969 BanksUsedFlow2(pcflow);
3974 Loop through the flow objects again and find the ones with the
3978 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3980 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3982 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
3983 pcflow_max_To = pcflow;
3985 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
3986 pcflow_max_From = pcflow;
3990 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
3991 PCFL(pcflow_max_To)->pc.seq,
3992 PCFL(pcflow_max_To)->ToConflicts);
3995 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
3996 PCFL(pcflow_max_From)->pc.seq,
3997 PCFL(pcflow_max_From)->FromConflicts);
4001 /*-----------------------------------------------------------------*/
4002 /*-----------------------------------------------------------------*/
4003 void DumpFlow(pBlock *pb)
4007 pCodeFlowLink *pcfl;
4010 fprintf(stderr,"Dump flow \n");
4011 pb->pcHead->print(stderr, pb->pcHead);
4013 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4014 pcflow->print(stderr,pcflow);
4016 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4018 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4020 if(!isPCFL(pcflow)) {
4021 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4024 fprintf(stderr,"dumping: ");
4025 pcflow->print(stderr,pcflow);
4026 FlowStats(PCFL(pcflow));
4028 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4030 pc = PCODE(pcfl->pcflow);
4032 fprintf(stderr, " from seq %d:\n",pc->seq);
4034 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4035 pc->print(stderr,pc);
4040 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4042 pc = PCODE(pcfl->pcflow);
4044 fprintf(stderr, " to seq %d:\n",pc->seq);
4046 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4047 pc->print(stderr,pc);
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 int OptimizepBlock(pBlock *pb)
4063 if(!pb || !peepOptimizing)
4066 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4068 for(pc = pb->pcHead; pc; pc = pc->next)
4069 matches += pCodePeepMatchRule(pc);
4072 pc = findNextInstruction(pb->pcHead);
4077 if(pCodePeepMatchRule(pc)) {
4082 pc = findNextInstruction(pcprev->next);
4084 pc = findNextInstruction(pb->pcHead);
4086 pc = findNextInstruction(pc->next);
4090 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4095 /*-----------------------------------------------------------------*/
4096 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4097 /*-----------------------------------------------------------------*/
4098 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4102 for(pc = pcs; pc; pc = pc->next) {
4104 if((pc->type == PC_OPCODE) &&
4106 (PCI(pc)->pcop->type == PO_LABEL) &&
4107 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4115 /*-----------------------------------------------------------------*/
4116 /*-----------------------------------------------------------------*/
4117 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4122 (PCI(pc)->pcop->type == PO_LABEL)) {
4124 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4126 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4128 free(pcol->pcop.name);
4130 sprintf(buffer,"_%05d_DS_",pcl->key);
4132 pcol->pcop.name = Safe_strdup(buffer);
4133 pcol->key = pcl->key;
4134 //pc->print(stderr,pc);
4141 /*-----------------------------------------------------------------*/
4142 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4143 /* pCode chain if they're not used. */
4144 /*-----------------------------------------------------------------*/
4145 void pBlockRemoveUnusedLabels(pBlock *pb)
4147 pCode *pc; pCodeLabel *pcl;
4152 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4154 pBranch *pbr = PCI(pc)->label;
4155 if(pbr && pbr->next) {
4156 pCode *pcd = pb->pcHead;
4158 //fprintf(stderr, "multiple labels\n");
4159 //pc->print(stderr,pc);
4164 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4165 //fprintf(stderr,"Used by:\n");
4166 //pcd->print(stderr,pcd);
4168 exchangeLabels(PCL(pbr->pc),pcd);
4177 for(pc = pb->pcHead; pc; pc = pc->next) {
4179 if(isPCL(pc)) // pc->type == PC_LABEL)
4181 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4182 pcl = PCL(PCI(pc)->label->pc);
4185 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4187 /* This pCode is a label, so search the pBlock to see if anyone
4190 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4191 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4192 /* Couldn't find an instruction that refers to this label
4193 * So, unlink the pCode label from it's pCode chain
4194 * and destroy the label */
4195 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4197 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4198 if(pc->type == PC_LABEL) {
4200 pCodeLabelDestruct(pc);
4202 unlinkpCodeFromBranch(pc, PCODE(pcl));
4203 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4214 /*-----------------------------------------------------------------*/
4215 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4216 /* chain and put them into pBranches that are */
4217 /* associated with the appropriate pCode */
4219 /*-----------------------------------------------------------------*/
4220 void pBlockMergeLabels(pBlock *pb)
4223 pCode *pc, *pcnext=NULL;
4228 /* First, Try to remove any unused labels */
4229 //pBlockRemoveUnusedLabels(pb);
4231 /* Now loop through the pBlock and merge the labels with the opcodes */
4233 for(pc = pb->pcHead; pc; pc = pc->next) {
4235 if(pc->type == PC_LABEL) {
4237 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4238 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4239 if((pcnext = findNextInstruction(pc) )) {
4241 pCode *pcn = pc->next;
4243 // Unlink the pCode label from it's pCode chain
4246 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4247 // And link it into the instruction's pBranch labels. (Note, since
4248 // it's possible to have multiple labels associated with one instruction
4249 // we must provide a means to accomodate the additional labels. Thus
4250 // the labels are placed into the singly-linked list "label" as
4251 // opposed to being a single member of the pCodeInstruction.)
4253 //_ALLOC(pbr,sizeof(pBranch));
4254 pbr = Safe_calloc(1,sizeof(pBranch));
4259 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4264 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4266 } else if(pc->type == PC_CSOURCE) {
4268 /* merge the source line symbolic info into the next instruction */
4269 if((pcnext = findNextInstruction(pc) )) {
4271 pCode *pcn = pc->next;
4273 // Unlink the pCode label from it's pCode chain
4275 PCI(pcnext)->cline = PCCS(pc);
4276 //fprintf(stderr, "merging CSRC\n");
4277 //genericPrint(stderr,pcnext);
4284 pBlockRemoveUnusedLabels(pb);
4288 /*-----------------------------------------------------------------*/
4289 /*-----------------------------------------------------------------*/
4290 int OptimizepCode(char dbName)
4292 #define MAX_PASSES 4
4301 DFPRINTF((stderr," Optimizing pCode\n"));
4305 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4306 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4307 matches += OptimizepBlock(pb);
4310 while(matches && ++passes < MAX_PASSES);
4315 /*-----------------------------------------------------------------*/
4316 /* popCopyGPR2Bit - copy a pcode operator */
4317 /*-----------------------------------------------------------------*/
4319 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4323 pcop = newpCodeOpBit(pc->name, bitval, 0);
4325 if( !( (pcop->type == PO_LABEL) ||
4326 (pcop->type == PO_LITERAL) ||
4327 (pcop->type == PO_STR) ))
4328 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4336 /*-----------------------------------------------------------------*/
4337 /*-----------------------------------------------------------------*/
4338 int InstructionRegBank(pCode *pc)
4342 if( (reg = getRegFromInstruction(pc)) == NULL)
4345 return REG_BANK(reg);
4350 /*-----------------------------------------------------------------*/
4351 /*-----------------------------------------------------------------*/
4352 void FixRegisterBanking(pBlock *pb)
4364 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4365 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4368 /* loop through all of the flow blocks with in one pblock */
4370 //fprintf(stderr,"Register banking\n");
4373 /* at this point, pc should point to a PC_FLOW object */
4376 /* for each flow block, determine the register banking
4381 //genericPrint(stderr, pc);
4383 reg = getRegFromInstruction(pc);
4386 fprintf(stderr, " %s ",reg->name);
4387 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4391 if(reg && REG_BANK(reg)!=cur_bank) {
4392 /* Examine the instruction before this one to make sure it is
4393 * not a skip type instruction */
4394 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4395 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4396 int b = cur_bank ^ REG_BANK(reg);
4398 //fprintf(stderr, "Cool! can switch banks\n");
4399 cur_bank = REG_BANK(reg);
4401 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4402 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4403 pCodeInsertAfter(pc->prev, new_pc);
4404 if(PCI(pc)->label) {
4405 PCI(new_pc)->label = PCI(pc)->label;
4406 PCI(pc)->label = NULL;
4409 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4410 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4411 pCodeInsertAfter(pc, new_pc);
4417 //fprintf(stderr, "Bummer can't switch banks\n");
4425 // } while(pc && !(isPCFL(pc)));
4430 if(pcprev && cur_bank) {
4431 /* Brute force - make sure that we point to bank 0 at the
4432 * end of each flow block */
4433 new_pc = newpCode(POC_BCF,
4434 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4435 pCodeInsertAfter(pcprev, new_pc);
4441 void pBlockDestruct(pBlock *pb)
4452 /*-----------------------------------------------------------------*/
4453 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4454 /* name dbName and combine them */
4455 /* into one block */
4456 /*-----------------------------------------------------------------*/
4457 void mergepBlocks(char dbName)
4460 pBlock *pb, *pbmerged = NULL,*pbn;
4462 pb = the_pFile->pbHead;
4464 //fprintf(stderr," merging blocks named %c\n",dbName);
4468 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4469 if( getpBlock_dbName(pb) == dbName) {
4471 //fprintf(stderr," merged block %c\n",dbName);
4476 addpCode2pBlock(pbmerged, pb->pcHead);
4477 /* addpCode2pBlock doesn't handle the tail: */
4478 pbmerged->pcTail = pb->pcTail;
4480 pb->prev->next = pbn;
4482 pbn->prev = pb->prev;
4487 //printpBlock(stderr, pbmerged);
4494 /*-----------------------------------------------------------------*/
4495 /* AnalyzeBanking - Called after the memory addresses have been */
4496 /* assigned to the registers. */
4498 /*-----------------------------------------------------------------*/
4499 void AnalyzeBanking(void)
4508 /* Phase 2 - Flow Analysis - Register Banking
4510 * In this phase, the individual flow blocks are examined
4511 * and register banking is fixed.
4514 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4515 //FixRegisterBanking(pb);
4517 /* Phase 2 - Flow Analysis
4519 * In this phase, the pCode is partition into pCodeFlow
4520 * blocks. The flow blocks mark the points where a continuous
4521 * stream of instructions changes flow (e.g. because of
4522 * a call or goto or whatever).
4525 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4529 /* Phase 2 - Flow Analysis - linking flow blocks
4531 * In this phase, the individual flow blocks are examined
4532 * to determine their order of excution.
4535 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4539 /* Phase x - Flow Analysis - Used Banks
4541 * In this phase, the individual flow blocks are examined
4542 * to determine the Register Banks they use
4545 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4548 /* Phase x - Flow Analysis - Used Banks
4550 * In this phase, the individual flow blocks are examined
4551 * to determine the Register Banks they use
4554 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4558 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4562 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4564 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4565 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4566 pcflow = pcflow->next) {
4568 FillFlow(PCFL(pcflow));
4572 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4574 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4575 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4576 pcflow = pcflow->next) {
4578 FlowStats(PCFL(pcflow));
4584 /*-----------------------------------------------------------------*/
4585 /* buildCallTree - look at the flow and extract all of the calls */
4587 /*-----------------------------------------------------------------*/
4588 set *register_usage(pBlock *pb);
4590 void buildCallTree(void )
4601 /* Now build the call tree.
4602 First we examine all of the pCodes for functions.
4603 Keep in mind that the function boundaries coincide
4604 with pBlock boundaries.
4606 The algorithm goes something like this:
4607 We have two nested loops. The outer loop iterates
4608 through all of the pBlocks/functions. The inner
4609 loop iterates through all of the pCodes for
4610 a given pBlock. When we begin iterating through
4611 a pBlock, the variable pc_fstart, pCode of the start
4612 of a function, is cleared. We then search for pCodes
4613 of type PC_FUNCTION. When one is encountered, we
4614 initialize pc_fstart to this and at the same time
4615 associate a new pBranch object that signifies a
4616 branch entry. If a return is found, then this signifies
4617 a function exit point. We'll link the pCodes of these
4618 returns to the matching pc_fstart.
4620 When we're done, a doubly linked list of pBranches
4621 will exist. The head of this list is stored in
4622 `the_pFile', which is the meta structure for all
4623 of the pCode. Look at the printCallTree function
4624 on how the pBranches are linked together.
4627 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4628 pCode *pc_fstart=NULL;
4629 for(pc = pb->pcHead; pc; pc = pc->next) {
4631 if (PCF(pc)->fname) {
4633 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4634 //fprintf(stderr," found main \n");
4635 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4639 pbr = Safe_calloc(1,sizeof(pBranch));
4640 pbr->pc = pc_fstart = pc;
4643 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4645 // Here's a better way of doing the same:
4646 addSet(&pb->function_entries, pc);
4649 // Found an exit point in a function, e.g. return
4650 // (Note, there may be more than one return per function)
4652 pBranchLink(PCF(pc_fstart), PCF(pc));
4654 addSet(&pb->function_exits, pc);
4656 } else if(isCALL(pc)) {
4657 addSet(&pb->function_calls,pc);
4662 /* Re-allocate the registers so that there are no collisions
4663 * between local variables when one function call another */
4665 pic14_deallocateAllRegs();
4667 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4674 /*-----------------------------------------------------------------*/
4675 /* AnalyzepCode - parse the pCode that has been generated and form */
4676 /* all of the logical connections. */
4678 /* Essentially what's done here is that the pCode flow is */
4680 /*-----------------------------------------------------------------*/
4682 void AnalyzepCode(char dbName)
4693 /* Phase 1 - Register allocation and peep hole optimization
4695 * The first part of the analysis is to determine the registers
4696 * that are used in the pCode. Once that is done, the peep rules
4697 * are applied to the code. We continue to loop until no more
4698 * peep rule optimizations are found (or until we exceed the
4699 * MAX_PASSES threshold).
4701 * When done, the required registers will be determined.
4707 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4708 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4710 /* First, merge the labels with the instructions */
4711 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4712 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4714 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4715 //fprintf(stderr," analyze and merging block %c\n",dbName);
4716 pBlockMergeLabels(pb);
4719 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4723 changes = OptimizepCode(dbName);
4725 } while(changes && (i++ < MAX_PASSES));
4730 /*-----------------------------------------------------------------*/
4731 /* ispCodeFunction - returns true if *pc is the pCode of a */
4733 /*-----------------------------------------------------------------*/
4734 bool ispCodeFunction(pCode *pc)
4737 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4743 /*-----------------------------------------------------------------*/
4744 /* findFunction - Search for a function by name (given the name) */
4745 /* in the set of all functions that are in a pBlock */
4746 /* (note - I expect this to change because I'm planning to limit */
4747 /* pBlock's to just one function declaration */
4748 /*-----------------------------------------------------------------*/
4749 pCode *findFunction(char *fname)
4756 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4758 pc = setFirstItem(pb->function_entries);
4761 if((pc->type == PC_FUNCTION) &&
4763 (strcmp(fname, PCF(pc)->fname)==0))
4766 pc = setNextItem(pb->function_entries);
4774 void MarkUsedRegisters(set *regset)
4779 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4780 r2 = pic14_regWithIdx(r1->rIdx);
4786 void pBlockStats(FILE *of, pBlock *pb)
4792 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4794 // for now just print the first element of each set
4795 pc = setFirstItem(pb->function_entries);
4797 fprintf(of,";entry: ");
4800 pc = setFirstItem(pb->function_exits);
4802 fprintf(of,";has an exit\n");
4806 pc = setFirstItem(pb->function_calls);
4808 fprintf(of,";functions called:\n");
4811 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4812 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4814 pc = setNextItem(pb->function_calls);
4818 r = setFirstItem(pb->tregisters);
4820 int n = elementsInSet(pb->tregisters);
4822 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4825 fprintf(of,"; %s\n",r->name);
4826 r = setNextItem(pb->tregisters);
4831 /*-----------------------------------------------------------------*/
4832 /*-----------------------------------------------------------------*/
4834 static void sequencepCode(void)
4840 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4842 pb->seq = GpCodeSequenceNumber+1;
4844 for( pc = pb->pcHead; pc; pc = pc->next)
4845 pc->seq = ++GpCodeSequenceNumber;
4851 /*-----------------------------------------------------------------*/
4852 /*-----------------------------------------------------------------*/
4853 set *register_usage(pBlock *pb)
4856 set *registers=NULL;
4857 set *registersInCallPath = NULL;
4859 /* check recursion */
4861 pc = setFirstItem(pb->function_entries);
4868 if(pc->type != PC_FUNCTION)
4869 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4871 pc = setFirstItem(pb->function_calls);
4872 for( ; pc; pc = setNextItem(pb->function_calls)) {
4874 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4875 char *dest = get_op_from_instruction(PCI(pc));
4877 pcn = findFunction(dest);
4879 registersInCallPath = register_usage(pcn->pb);
4881 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4886 pBlockStats(stderr,pb); // debug
4889 // Mark the registers in this block as used.
4891 MarkUsedRegisters(pb->tregisters);
4892 if(registersInCallPath) {
4893 /* registers were used in the functions this pBlock has called */
4894 /* so now, we need to see if these collide with the ones we are */
4897 regs *r1,*r2, *newreg;
4899 DFPRINTF((stderr,"comparing registers\n"));
4901 r1 = setFirstItem(registersInCallPath);
4904 r2 = setFirstItem(pb->tregisters);
4906 while(r2 && (r1->type != REG_STK)) {
4908 if(r2->rIdx == r1->rIdx) {
4909 newreg = pic14_findFreeReg(REG_GPR);
4913 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4917 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4918 r1->rIdx, newreg->rIdx));
4919 r2->rIdx = newreg->rIdx;
4920 //if(r2->name) free(r2->name);
4922 r2->name = Safe_strdup(newreg->name);
4926 newreg->wasUsed = 1;
4928 r2 = setNextItem(pb->tregisters);
4931 r1 = setNextItem(registersInCallPath);
4934 /* Collisions have been resolved. Now free the registers in the call path */
4935 r1 = setFirstItem(registersInCallPath);
4937 if(r1->type != REG_STK) {
4938 newreg = pic14_regWithIdx(r1->rIdx);
4941 r1 = setNextItem(registersInCallPath);
4945 // MarkUsedRegisters(pb->registers);
4947 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4950 DFPRINTF((stderr,"returning regs\n"));
4952 DFPRINTF((stderr,"not returning regs\n"));
4954 DFPRINTF((stderr,"pBlock after register optim.\n"));
4955 pBlockStats(stderr,pb); // debug
4961 /*-----------------------------------------------------------------*/
4962 /* printCallTree - writes the call tree to a file */
4964 /*-----------------------------------------------------------------*/
4965 void pct2(FILE *of,pBlock *pb,int indent)
4969 // set *registersInCallPath = NULL;
4975 return; //recursion ?
4977 pc = setFirstItem(pb->function_entries);
4984 for(i=0;i<indent;i++) // Indentation
4987 if(pc->type == PC_FUNCTION)
4988 fprintf(of,"%s\n",PCF(pc)->fname);
4993 pc = setFirstItem(pb->function_calls);
4994 for( ; pc; pc = setNextItem(pb->function_calls)) {
4996 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4997 char *dest = get_op_from_instruction(PCI(pc));
4999 pcn = findFunction(dest);
5001 pct2(of,pcn->pb,indent+1);
5003 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5011 /*-----------------------------------------------------------------*/
5012 /* printCallTree - writes the call tree to a file */
5014 /*-----------------------------------------------------------------*/
5016 void printCallTree(FILE *of)
5028 fprintf(of, "\npBlock statistics\n");
5029 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5034 fprintf(of,"Call Tree\n");
5035 pbr = the_pFile->functions;
5039 if(!ispCodeFunction(pc))
5040 fprintf(of,"bug in call tree");
5043 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5045 while(pc->next && !ispCodeFunction(pc->next)) {
5047 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5048 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5056 fprintf(of,"\n**************\n\na better call tree\n");
5057 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5062 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5063 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5069 /*-----------------------------------------------------------------*/
5071 /*-----------------------------------------------------------------*/
5073 void InlineFunction(pBlock *pb)
5081 pc = setFirstItem(pb->function_calls);
5083 for( ; pc; pc = setNextItem(pb->function_calls)) {
5086 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5092 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5094 //fprintf(stderr,"Cool can inline:\n");
5095 //pcn->print(stderr,pcn);
5097 //fprintf(stderr,"recursive call Inline\n");
5098 InlineFunction(pcn->pb);
5099 //fprintf(stderr,"return from recursive call Inline\n");
5102 At this point, *pc points to a CALL mnemonic, and
5103 *pcn points to the function that is being called.
5105 To in-line this call, we need to remove the CALL
5106 and RETURN(s), and link the function pCode in with
5112 /* Remove the CALL */
5116 /* remove callee pBlock from the pBlock linked list */
5117 removepBlock(pcn->pb);
5125 /* Remove the Function pCode */
5126 pct = findNextInstruction(pcn->next);
5128 /* Link the function with the callee */
5129 pc->next = pcn->next;
5130 pcn->next->prev = pc;
5132 /* Convert the function name into a label */
5134 pbr = Safe_calloc(1,sizeof(pBranch));
5135 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5137 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5138 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5140 /* turn all of the return's except the last into goto's */
5141 /* check case for 2 instruction pBlocks */
5142 pce = findNextInstruction(pcn->next);
5144 pCode *pce_next = findNextInstruction(pce->next);
5146 if(pce_next == NULL) {
5147 /* found the last return */
5148 pCode *pc_call_next = findNextInstruction(pc_call->next);
5150 //fprintf(stderr,"found last return\n");
5151 //pce->print(stderr,pce);
5152 pce->prev->next = pc_call->next;
5153 pc_call->next->prev = pce->prev;
5154 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5164 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5170 /*-----------------------------------------------------------------*/
5172 /*-----------------------------------------------------------------*/
5174 void InlinepCode(void)
5183 if(!functionInlining)
5186 /* Loop through all of the function definitions and count the
5187 * number of times each one is called */
5188 //fprintf(stderr,"inlining %d\n",__LINE__);
5190 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5192 pc = setFirstItem(pb->function_calls);
5194 for( ; pc; pc = setNextItem(pb->function_calls)) {
5197 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5198 if(pcn && isPCF(pcn)) {
5199 PCF(pcn)->ncalled++;
5202 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5207 //fprintf(stderr,"inlining %d\n",__LINE__);
5209 /* Now, Loop through the function definitions again, but this
5210 * time inline those functions that have only been called once. */
5212 InlineFunction(the_pFile->pbHead);
5213 //fprintf(stderr,"inlining %d\n",__LINE__);
5215 for(pb = the_pFile->pbHead; pb; pb = pb->next)