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,char *buff,int buf_size);
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__);
1164 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1172 #else // USE_VSNPRINTF
1174 // This version is *not* safe, despite the name.
1176 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1180 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1185 va_start(val, format);
1187 vsprintf(buffer, format, val);
1190 len = strlen(buffer);
1192 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1193 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1196 strcpy(*str, buffer);
1202 #endif // USE_VSNPRINTF
1205 extern void initStack(int base_address, int size);
1206 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1207 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1208 extern void init_pic(char *);
1210 void pCodeInitRegisters(void)
1213 initStack(0xfff, 8);
1214 init_pic(port->processor);
1216 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1217 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1218 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1219 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1220 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1221 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1223 pc_status.rIdx = IDX_STATUS;
1224 pc_fsr.rIdx = IDX_FSR;
1225 pc_indf.rIdx = IDX_INDF;
1226 pc_intcon.rIdx = IDX_INTCON;
1227 pc_pcl.rIdx = IDX_PCL;
1228 pc_pclath.rIdx = IDX_PCLATH;
1230 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1231 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1232 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1234 pc_kzero.rIdx = IDX_KZ;
1235 pc_wsave.rIdx = IDX_WSAVE;
1236 pc_ssave.rIdx = IDX_SSAVE;
1240 /*-----------------------------------------------------------------*/
1241 /* mnem2key - convert a pic mnemonic into a hash key */
1242 /* (BTW - this spreads the mnemonics quite well) */
1244 /*-----------------------------------------------------------------*/
1246 int mnem2key(char const *mnem)
1255 key += toupper(*mnem++) +1;
1259 return (key & 0x1f);
1263 void pic14initMnemonics(void)
1268 pCodeInstruction *pci;
1270 if(mnemonics_initialized)
1273 //FIXME - probably should NULL out the array before making the assignments
1274 //since we check the array contents below this initialization.
1276 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1277 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1278 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1279 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1280 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1281 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1282 pic14Mnemonics[POC_BCF] = &pciBCF;
1283 pic14Mnemonics[POC_BSF] = &pciBSF;
1284 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1285 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1286 pic14Mnemonics[POC_CALL] = &pciCALL;
1287 pic14Mnemonics[POC_COMF] = &pciCOMF;
1288 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1289 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1290 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1291 pic14Mnemonics[POC_DECF] = &pciDECF;
1292 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1293 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1294 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1295 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1296 pic14Mnemonics[POC_INCF] = &pciINCF;
1297 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1298 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1299 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1300 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1301 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1302 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1303 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1304 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1305 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1306 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1307 pic14Mnemonics[POC_NOP] = &pciNOP;
1308 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1309 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1310 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1311 pic14Mnemonics[POC_RLF] = &pciRLF;
1312 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1313 pic14Mnemonics[POC_RRF] = &pciRRF;
1314 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1315 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1316 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1317 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1318 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1319 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1320 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1321 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1322 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1323 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1325 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1326 if(pic14Mnemonics[i])
1327 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1328 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1331 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1332 pci = hTabNextItem(pic14MnemonicsHash, &key);
1335 mnemonics_initialized = 1;
1338 int getpCodePeepCommand(char *cmd);
1340 int getpCode(char *mnem,unsigned dest)
1343 pCodeInstruction *pci;
1344 int key = mnem2key(mnem);
1346 if(!mnemonics_initialized)
1347 pic14initMnemonics();
1349 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1353 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1354 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1358 pci = hTabNextItemWK (pic14MnemonicsHash);
1365 /*-----------------------------------------------------------------*
1366 * pic14initpCodePeepCommands
1368 *-----------------------------------------------------------------*/
1369 void pic14initpCodePeepCommands(void)
1377 hTabAddItem(&pic14pCodePeepCommandsHash,
1378 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1380 } while (peepCommands[i].cmd);
1382 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1385 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1386 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1391 /*-----------------------------------------------------------------
1394 *-----------------------------------------------------------------*/
1396 int getpCodePeepCommand(char *cmd)
1400 int key = mnem2key(cmd);
1403 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1406 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1407 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1411 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1418 char getpBlock_dbName(pBlock *pb)
1424 return pb->cmemmap->dbName;
1428 void pBlockConvert2ISR(pBlock *pb)
1439 /*-----------------------------------------------------------------*/
1440 /* movepBlock2Head - given the dbname of a pBlock, move all */
1441 /* instances to the front of the doubly linked */
1442 /* list of pBlocks */
1443 /*-----------------------------------------------------------------*/
1445 void movepBlock2Head(char dbName)
1449 pb = the_pFile->pbHead;
1453 if(getpBlock_dbName(pb) == dbName) {
1454 pBlock *pbn = pb->next;
1455 pb->next = the_pFile->pbHead;
1456 the_pFile->pbHead->prev = pb;
1457 the_pFile->pbHead = pb;
1460 pb->prev->next = pbn;
1462 // If the pBlock that we just moved was the last
1463 // one in the link of all of the pBlocks, then we
1464 // need to point the tail to the block just before
1465 // the one we moved.
1466 // Note: if pb->next is NULL, then pb must have
1467 // been the last pBlock in the chain.
1470 pbn->prev = pb->prev;
1472 the_pFile->pbTail = pb->prev;
1483 void copypCode(FILE *of, char dbName)
1487 if(!of || !the_pFile)
1490 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1491 if(getpBlock_dbName(pb) == dbName) {
1498 void pcode_test(void)
1501 DFPRINTF((stderr,"pcode is alive!\n"));
1511 /* create the file name */
1512 strcpy(buffer,srcFileName);
1513 strcat(buffer,".p");
1515 if( !(pFile = fopen(buffer, "w" ))) {
1516 werror(E_FILE_OPEN_ERR,buffer);
1520 fprintf(pFile,"pcode dump\n\n");
1522 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1523 fprintf(pFile,"\n\tNew pBlock\n\n");
1525 fprintf(pFile,"%s",pb->cmemmap->sname);
1527 fprintf(pFile,"internal pblock");
1529 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1530 printpBlock(pFile,pb);
1534 /*-----------------------------------------------------------------*/
1535 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1536 /* ister, RegCond will return the bit being referenced. */
1538 /* fixme - why not just OR in the pcop bit field */
1539 /*-----------------------------------------------------------------*/
1541 static int RegCond(pCodeOp *pcop)
1547 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1548 switch(PCORB(pcop)->bit) {
1562 /*-----------------------------------------------------------------*/
1563 /* newpCode - create and return a newly initialized pCode */
1565 /* fixme - rename this */
1567 /* The purpose of this routine is to create a new Instruction */
1568 /* pCode. This is called by gen.c while the assembly code is being */
1572 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1573 /* (note that the op is analogous to but not the */
1574 /* same thing as the opcode of the instruction.) */
1575 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1578 /* a pointer to the new malloc'd pCode is returned. */
1582 /*-----------------------------------------------------------------*/
1583 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1585 pCodeInstruction *pci ;
1587 if(!mnemonics_initialized)
1588 pic14initMnemonics();
1590 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1592 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1593 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1596 if(pci->inCond == PCC_EXAMINE_PCOP)
1597 pci->inCond = RegCond(pcop);
1599 if(pci->outCond == PCC_EXAMINE_PCOP)
1600 pci->outCond = RegCond(pcop);
1602 pci->pc.prev = pci->pc.next = NULL;
1603 return (pCode *)pci;
1606 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1612 /*-----------------------------------------------------------------*/
1613 /* newpCodeWild - create a "wild" as in wild card pCode */
1615 /* Wild pcodes are used during the peep hole optimizer to serve */
1616 /* as place holders for any instruction. When a snippet of code is */
1617 /* compared to a peep hole rule, the wild card opcode will match */
1618 /* any instruction. However, the optional operand and label are */
1619 /* additional qualifiers that must also be matched before the */
1620 /* line (of assembly code) is declared matched. Note that the */
1621 /* operand may be wild too. */
1623 /* Note, a wild instruction is specified just like a wild var: */
1624 /* %4 ; A wild instruction, */
1625 /* See the peeph.def file for additional examples */
1627 /*-----------------------------------------------------------------*/
1629 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1634 pcw = Safe_calloc(1,sizeof(pCodeWild));
1636 pcw->pci.pc.type = PC_WILD;
1637 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1638 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1639 pcw->pci.pc.pb = NULL;
1641 // pcw->pci.pc.analyze = genericAnalyze;
1642 pcw->pci.pc.destruct = genericDestruct;
1643 pcw->pci.pc.print = genericPrint;
1645 pcw->id = pCodeID; // this is the 'n' in %n
1646 pcw->operand = optional_operand;
1647 pcw->label = optional_label;
1649 pcw->mustBeBitSkipInst = 0;
1650 pcw->mustNotBeBitSkipInst = 0;
1651 pcw->invertBitSkipInst = 0;
1653 return ( (pCode *)pcw);
1657 /*-----------------------------------------------------------------*/
1658 /* newPcodeInlineP - create a new pCode from a char string */
1659 /*-----------------------------------------------------------------*/
1662 pCode *newpCodeInlineP(char *cP)
1667 pcc = Safe_calloc(1,sizeof(pCodeComment));
1669 pcc->pc.type = PC_INLINE;
1670 pcc->pc.prev = pcc->pc.next = NULL;
1671 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1674 // pcc->pc.analyze = genericAnalyze;
1675 pcc->pc.destruct = genericDestruct;
1676 pcc->pc.print = genericPrint;
1679 pcc->comment = Safe_strdup(cP);
1681 pcc->comment = NULL;
1683 return ( (pCode *)pcc);
1687 /*-----------------------------------------------------------------*/
1688 /* newPcodeCharP - create a new pCode from a char string */
1689 /*-----------------------------------------------------------------*/
1691 pCode *newpCodeCharP(char *cP)
1696 pcc = Safe_calloc(1,sizeof(pCodeComment));
1698 pcc->pc.type = PC_COMMENT;
1699 pcc->pc.prev = pcc->pc.next = NULL;
1700 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1703 // pcc->pc.analyze = genericAnalyze;
1704 pcc->pc.destruct = genericDestruct;
1705 pcc->pc.print = genericPrint;
1708 pcc->comment = Safe_strdup(cP);
1710 pcc->comment = NULL;
1712 return ( (pCode *)pcc);
1716 /*-----------------------------------------------------------------*/
1717 /* newpCodeFunction - */
1718 /*-----------------------------------------------------------------*/
1721 pCode *newpCodeFunction(char *mod,char *f)
1725 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1726 //_ALLOC(pcf,sizeof(pCodeFunction));
1728 pcf->pc.type = PC_FUNCTION;
1729 pcf->pc.prev = pcf->pc.next = NULL;
1730 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1733 // pcf->pc.analyze = genericAnalyze;
1734 pcf->pc.destruct = genericDestruct;
1735 pcf->pc.print = pCodePrintFunction;
1740 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1741 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1742 strcpy(pcf->modname,mod);
1744 pcf->modname = NULL;
1747 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1748 pcf->fname = Safe_calloc(1,strlen(f)+1);
1749 strcpy(pcf->fname,f);
1753 return ( (pCode *)pcf);
1757 /*-----------------------------------------------------------------*/
1759 /*-----------------------------------------------------------------*/
1761 void destructpCodeFlow(pCode *pc)
1763 if(!pc || !isPCFL(pc))
1767 free(PCFL(pc)->uses);
1775 pCode *newpCodeFlow(void )
1779 //_ALLOC(pcflow,sizeof(pCodeFlow));
1780 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1782 pcflow->pc.type = PC_FLOW;
1783 pcflow->pc.prev = pcflow->pc.next = NULL;
1784 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1785 pcflow->pc.pb = NULL;
1787 // pcflow->pc.analyze = genericAnalyze;
1788 pcflow->pc.destruct = destructpCodeFlow;
1789 pcflow->pc.print = genericPrint;
1791 pcflow->pc.seq = GpcFlowSeq++;
1794 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1796 pcflow->from = pcflow->to = NULL;
1798 pcflow->inCond = PCC_NONE;
1799 pcflow->outCond = PCC_NONE;
1801 pcflow->firstBank = -1;
1802 pcflow->lastBank = -1;
1804 pcflow->FromConflicts = 0;
1805 pcflow->ToConflicts = 0;
1808 return ( (pCode *)pcflow);
1812 /*-----------------------------------------------------------------*/
1813 /*-----------------------------------------------------------------*/
1814 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1816 pCodeFlowLink *pcflowLink;
1818 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1820 pcflowLink->pcflow = pcflow;
1821 pcflowLink->bank_conflict = 0;
1826 /*-----------------------------------------------------------------*/
1827 /* newpCodeCSource - create a new pCode Source Symbol */
1828 /*-----------------------------------------------------------------*/
1830 pCode *newpCodeCSource(int ln, char *f, char *l)
1835 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1837 pccs->pc.type = PC_CSOURCE;
1838 pccs->pc.prev = pccs->pc.next = NULL;
1841 pccs->pc.destruct = genericDestruct;
1842 pccs->pc.print = genericPrint;
1844 pccs->line_number = ln;
1846 pccs->line = Safe_strdup(l);
1851 pccs->file_name = Safe_strdup(f);
1853 pccs->file_name = NULL;
1855 return ( (pCode *)pccs);
1858 /*-----------------------------------------------------------------*/
1859 /* pCodeLabelDestruct - free memory used by a label. */
1860 /*-----------------------------------------------------------------*/
1861 static void pCodeLabelDestruct(pCode *pc)
1867 if((pc->type == PC_LABEL) && PCL(pc)->label)
1868 free(PCL(pc)->label);
1874 pCode *newpCodeLabel(char *name, int key)
1880 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1882 pcl->pc.type = PC_LABEL;
1883 pcl->pc.prev = pcl->pc.next = NULL;
1884 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1887 // pcl->pc.analyze = genericAnalyze;
1888 pcl->pc.destruct = pCodeLabelDestruct;
1889 pcl->pc.print = pCodePrintLabel;
1895 sprintf(s,"_%05d_DS_",key);
1900 pcl->label = Safe_strdup(s);
1903 return ( (pCode *)pcl);
1908 /*-----------------------------------------------------------------*/
1909 /* newpBlock - create and return a pointer to a new pBlock */
1910 /*-----------------------------------------------------------------*/
1911 pBlock *newpBlock(void)
1916 PpB = Safe_calloc(1,sizeof(pBlock) );
1917 PpB->next = PpB->prev = NULL;
1919 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1920 PpB->tregisters = NULL;
1927 /*-----------------------------------------------------------------*/
1928 /* newpCodeChain - create a new chain of pCodes */
1929 /*-----------------------------------------------------------------*
1931 * This function will create a new pBlock and the pointer to the
1932 * pCode that is passed in will be the first pCode in the block.
1933 *-----------------------------------------------------------------*/
1936 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1939 pBlock *pB = newpBlock();
1941 pB->pcHead = pB->pcTail = pc;
1948 /*-----------------------------------------------------------------*/
1949 /* newpCodeOpLabel - Create a new label given the key */
1950 /* Note, a negative key means that the label is part of wild card */
1951 /* (and hence a wild card label) used in the pCodePeep */
1952 /* optimizations). */
1953 /*-----------------------------------------------------------------*/
1955 pCodeOp *newpCodeOpLabel(char *name, int key)
1958 static int label_key=-1;
1962 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1963 pcop->type = PO_LABEL;
1968 sprintf(s=buffer,"_%05d_DS_",key);
1970 s = name, key = label_key--;
1973 pcop->name = Safe_strdup(s);
1975 ((pCodeOpLabel *)pcop)->key = key;
1980 /*-----------------------------------------------------------------*/
1981 /*-----------------------------------------------------------------*/
1982 pCodeOp *newpCodeOpLit(int lit)
1988 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1989 pcop->type = PO_LITERAL;
1993 sprintf(s,"0x%02x",lit);
1995 pcop->name = Safe_strdup(s);
1998 ((pCodeOpLit *)pcop)->lit = lit;
2003 /*-----------------------------------------------------------------*/
2004 /*-----------------------------------------------------------------*/
2005 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2009 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2010 pcop->type = PO_IMMEDIATE;
2012 pcop->name = Safe_strdup(name);
2013 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2019 PCOI(pcop)->index = index;
2020 PCOI(pcop)->offset = offset;
2021 PCOI(pcop)->_const = code_space;
2026 /*-----------------------------------------------------------------*/
2027 /*-----------------------------------------------------------------*/
2028 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2034 if(!pcwb || !subtype) {
2035 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2039 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2040 pcop->type = PO_WILD;
2041 sprintf(s,"%%%d",id);
2042 pcop->name = Safe_strdup(s);
2044 PCOW(pcop)->id = id;
2045 PCOW(pcop)->pcwb = pcwb;
2046 PCOW(pcop)->subtype = subtype;
2047 PCOW(pcop)->matched = NULL;
2052 /*-----------------------------------------------------------------*/
2053 /*-----------------------------------------------------------------*/
2054 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2058 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2059 pcop->type = PO_GPR_BIT;
2061 pcop->name = Safe_strdup(s);
2065 PCORB(pcop)->bit = bit;
2066 PCORB(pcop)->inBitSpace = inBitSpace;
2071 /*-----------------------------------------------------------------*
2072 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2074 * If rIdx >=0 then a specific register from the set of registers
2075 * will be selected. If rIdx <0, then a new register will be searched
2077 *-----------------------------------------------------------------*/
2079 pCodeOp *newpCodeOpReg(int rIdx)
2083 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2088 PCOR(pcop)->rIdx = rIdx;
2089 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2091 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2094 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2095 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2098 pcop->type = PCOR(pcop)->r->pc_type;
2103 pCodeOp *newpCodeOpRegFromStr(char *name)
2107 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2108 PCOR(pcop)->r = allocRegByName(name, 1);
2109 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2110 pcop->type = PCOR(pcop)->r->pc_type;
2111 pcop->name = PCOR(pcop)->r->name;
2116 /*-----------------------------------------------------------------*/
2117 /*-----------------------------------------------------------------*/
2119 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2126 pcop = newpCodeOpBit(name, -1,0);
2130 pcop = newpCodeOpLit(-1);
2134 pcop = newpCodeOpLabel(NULL,-1);
2137 pcop = newpCodeOpReg(-1);
2141 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2144 pcop->name = Safe_strdup(name);
2152 /*-----------------------------------------------------------------*/
2153 /*-----------------------------------------------------------------*/
2154 void pCodeConstString(char *name, char *value)
2158 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2163 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2167 sprintf(buffer,"; %s = %s",name,value);
2169 addpCode2pBlock(pb,newpCodeCharP(buffer));
2170 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2173 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2179 /*-----------------------------------------------------------------*/
2180 /*-----------------------------------------------------------------*/
2181 void pCodeReadCodeTable(void)
2185 fprintf(stderr, " %s\n",__FUNCTION__);
2187 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2191 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2192 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2193 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2194 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2196 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2197 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2198 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2199 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2204 /*-----------------------------------------------------------------*/
2205 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2206 /*-----------------------------------------------------------------*/
2207 void addpCode2pBlock(pBlock *pb, pCode *pc)
2210 /* If this is the first pcode to be added to a block that
2211 * was initialized with a NULL pcode, then go ahead and
2212 * make this pcode the head and tail */
2213 pb->pcHead = pb->pcTail = pc;
2215 pb->pcTail->next = pc;
2216 pc->prev = pb->pcTail;
2223 /*-----------------------------------------------------------------*/
2224 /* addpBlock - place a pBlock into the pFile */
2225 /*-----------------------------------------------------------------*/
2226 void addpBlock(pBlock *pb)
2228 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2231 /* First time called, we'll pass through here. */
2232 //_ALLOC(the_pFile,sizeof(pFile));
2233 the_pFile = Safe_calloc(1,sizeof(pFile));
2234 the_pFile->pbHead = the_pFile->pbTail = pb;
2235 the_pFile->functions = NULL;
2239 the_pFile->pbTail->next = pb;
2240 pb->prev = the_pFile->pbTail;
2242 the_pFile->pbTail = pb;
2245 /*-----------------------------------------------------------------*/
2246 /* removepBlock - remove a pBlock from the pFile */
2247 /*-----------------------------------------------------------------*/
2248 void removepBlock(pBlock *pb)
2256 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2258 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2261 if(pbs == the_pFile->pbHead)
2262 the_pFile->pbHead = pbs->next;
2264 if (pbs == the_pFile->pbTail)
2265 the_pFile->pbTail = pbs->prev;
2268 pbs->next->prev = pbs->prev;
2271 pbs->prev->next = pbs->next;
2278 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2282 /*-----------------------------------------------------------------*/
2283 /* printpCode - write the contents of a pCode to a file */
2284 /*-----------------------------------------------------------------*/
2285 void printpCode(FILE *of, pCode *pc)
2296 fprintf(of,"warning - unable to print pCode\n");
2299 /*-----------------------------------------------------------------*/
2300 /* printpBlock - write the contents of a pBlock to a file */
2301 /*-----------------------------------------------------------------*/
2302 void printpBlock(FILE *of, pBlock *pb)
2312 for(pc = pb->pcHead; pc; pc = pc->next)
2317 /*-----------------------------------------------------------------*/
2319 /* pCode processing */
2323 /*-----------------------------------------------------------------*/
2325 static void unlinkPC(pCode *pc)
2331 fprintf(stderr,"Unlinking: ");
2332 printpCode(stderr, pc);
2335 pc->prev->next = pc->next;
2337 pc->next->prev = pc->prev;
2339 pc->prev = pc->next = NULL;
2342 static void genericDestruct(pCode *pc)
2344 //fprintf(stderr,"warning, calling default pCode destructor\n");
2353 /*-----------------------------------------------------------------*/
2354 /*-----------------------------------------------------------------*/
2355 void pBlockRegs(FILE *of, pBlock *pb)
2360 r = setFirstItem(pb->tregisters);
2362 r = setNextItem(pb->tregisters);
2367 /*-----------------------------------------------------------------*/
2368 /*-----------------------------------------------------------------*/
2369 char *get_op(pCodeOp *pcop,char *buffer, int size)
2382 switch(pcop->type) {
2385 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2386 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2388 return PCOR(pcop)->r->name;
2391 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2392 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2396 // return PCOR(pcc->pcop)->r)->name;
2399 //size = sizeof(buffer);
2400 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2401 if(PCOI(pcop)->_const) {
2403 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2404 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2407 8 * PCOI(pcop)->offset );
2409 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2412 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2413 SAFE_snprintf(&s,&size,"(%s + %d)",
2415 PCOI(pcop)->index );
2417 SAFE_snprintf(&s,&size,"%s",pcop->name);
2424 //size = sizeof(buffer);
2425 if( PCOR(pcop)->instance) {
2426 SAFE_snprintf(&s,&size,"(%s + %d)",
2428 PCOR(pcop)->instance );
2429 //fprintf(stderr,"PO_DIR %s\n",buffer);
2431 SAFE_snprintf(&s,&size,"%s",pcop->name);
2441 return "NO operand";
2445 /*-----------------------------------------------------------------*/
2446 /*-----------------------------------------------------------------*/
2447 static char *get_op_from_instruction( pCodeInstruction *pcc)
2451 return get_op(pcc->pcop,NULL,0);
2453 return ("ERROR Null: "__FUNCTION__);
2457 /*-----------------------------------------------------------------*/
2458 /*-----------------------------------------------------------------*/
2459 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2462 fprintf(of,"pcodeopprint- not implemented\n");
2465 /*-----------------------------------------------------------------*/
2466 /*-----------------------------------------------------------------*/
2467 char *pCode2str(char *str, int size, pCode *pc)
2475 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2477 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2479 if(PCI(pc)->isBitInst) {
2480 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2481 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2482 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2483 PCI(pc)->pcop->name ,
2484 PCI(pc)->pcop->name );
2486 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2487 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2488 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2489 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2491 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2492 //PCI(pc)->pcop->t.bit );
2495 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2496 if( PCI(pc)->num_ops == 2)
2497 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2499 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2502 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2504 if( PCI(pc)->num_ops == 2)
2505 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2513 /* assuming that comment ends with a \n */
2514 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2518 /* assuming that inline code ends with a \n */
2519 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2523 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2526 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2529 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2532 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2535 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2544 /*-----------------------------------------------------------------*/
2545 /* genericPrint - the contents of a pCode to a file */
2546 /*-----------------------------------------------------------------*/
2547 static void genericPrint(FILE *of, pCode *pc)
2555 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2559 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2563 // If the opcode has a label, print that first
2565 pBranch *pbl = PCI(pc)->label;
2566 while(pbl && pbl->pc) {
2567 if(pbl->pc->type == PC_LABEL)
2568 pCodePrintLabel(of, pbl->pc);
2574 genericPrint(of,PCODE(PCI(pc)->cline));
2579 pCode2str(str, 256, pc);
2581 fprintf(of,"%s",str);
2584 fprintf(of, "\t;key=%03x",pc->seq);
2586 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2590 pBranch *dpb = pc->to; // debug
2592 switch ( dpb->pc->type) {
2594 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2597 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2600 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2603 fprintf(of, "\t;flow");
2617 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2618 if(PCW(pc)->pci.label)
2619 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2621 if(PCW(pc)->operand) {
2622 fprintf(of,";\toperand ");
2623 pCodeOpPrint(of,PCW(pc)->operand );
2628 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2632 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2636 fprintf(of,"unknown pCode type %d\n",pc->type);
2641 /*-----------------------------------------------------------------*/
2642 /* pCodePrintFunction - prints function begin/end */
2643 /*-----------------------------------------------------------------*/
2645 static void pCodePrintFunction(FILE *of, pCode *pc)
2651 if( ((pCodeFunction *)pc)->modname)
2652 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2654 if(PCF(pc)->fname) {
2655 pBranch *exits = PCF(pc)->to;
2657 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2660 exits = exits->next;
2663 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2666 if((PCF(pc)->from &&
2667 PCF(pc)->from->pc->type == PC_FUNCTION &&
2668 PCF(PCF(pc)->from->pc)->fname) )
2669 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2671 fprintf(of,"; exit point [can't find entry point]\n");
2674 /*-----------------------------------------------------------------*/
2675 /* pCodePrintLabel - prints label */
2676 /*-----------------------------------------------------------------*/
2678 static void pCodePrintLabel(FILE *of, pCode *pc)
2685 fprintf(of,"%s\n",PCL(pc)->label);
2686 else if (PCL(pc)->key >=0)
2687 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2689 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2692 /*-----------------------------------------------------------------*/
2693 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2694 /* remove it if it is found. */
2695 /*-----------------------------------------------------------------*/
2696 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2703 if(pcl->type == PC_OPCODE)
2704 b = PCI(pcl)->label;
2706 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2711 //fprintf (stderr, "%s \n",__FUNCTION__);
2712 //pcl->print(stderr,pcl);
2713 //pc->print(stderr,pc);
2716 //fprintf (stderr, "found label\n");
2720 bprev->next = b->next; /* Not first pCode in chain */
2724 PCI(pcl)->label = b->next; /* First pCode in chain */
2727 return; /* A label can't occur more than once */
2735 /*-----------------------------------------------------------------*/
2736 /*-----------------------------------------------------------------*/
2737 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2753 /*-----------------------------------------------------------------*/
2754 /* pBranchLink - given two pcodes, this function will link them */
2755 /* together through their pBranches */
2756 /*-----------------------------------------------------------------*/
2757 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2761 // Declare a new branch object for the 'from' pCode.
2763 //_ALLOC(b,sizeof(pBranch));
2764 b = Safe_calloc(1,sizeof(pBranch));
2765 b->pc = PCODE(t); // The link to the 'to' pCode.
2768 f->to = pBranchAppend(f->to,b);
2770 // Now do the same for the 'to' pCode.
2772 //_ALLOC(b,sizeof(pBranch));
2773 b = Safe_calloc(1,sizeof(pBranch));
2777 t->from = pBranchAppend(t->from,b);
2782 /*-----------------------------------------------------------------*/
2783 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2785 /*-----------------------------------------------------------------*/
2786 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2799 /*-----------------------------------------------------------------*/
2800 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2801 /*-----------------------------------------------------------------*/
2802 static void pCodeUnlink(pCode *pc)
2807 if(!pc->prev || !pc->next) {
2808 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2812 /* first remove the pCode from the chain */
2813 pc->prev->next = pc->next;
2814 pc->next->prev = pc->prev;
2816 /* Now for the hard part... */
2818 /* Remove the branches */
2822 pc1 = pb1->pc; /* Get the pCode that branches to the
2823 * one we're unlinking */
2825 /* search for the link back to this pCode (the one we're
2827 if(pb2 = pBranchFind(pc1->to,pc)) {
2828 pb2->pc = pc->to->pc; // make the replacement
2830 /* if the pCode we're unlinking contains multiple 'to'
2831 * branches (e.g. this a skip instruction) then we need
2832 * to copy these extra branches to the chain. */
2834 pBranchAppend(pb2, pc->to->next);
2843 /*-----------------------------------------------------------------*/
2844 /*-----------------------------------------------------------------*/
2846 static void genericAnalyze(pCode *pc)
2856 // Go through the pCodes that are in pCode chain and link
2857 // them together through the pBranches. Note, the pCodes
2858 // are linked together as a contiguous stream like the
2859 // assembly source code lines. The linking here mimics this
2860 // except that comments are not linked in.
2862 pCode *npc = pc->next;
2864 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2865 pBranchLink(pc,npc);
2870 /* reached the end of the pcode chain without finding
2871 * an instruction we could link to. */
2875 fprintf(stderr,"analyze PC_FLOW\n");
2882 /*-----------------------------------------------------------------*/
2883 /*-----------------------------------------------------------------*/
2884 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2888 if(pc->type == PC_LABEL) {
2889 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2892 if(pc->type == PC_OPCODE) {
2893 pbr = PCI(pc)->label;
2895 if(pbr->pc->type == PC_LABEL) {
2896 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2906 /*-----------------------------------------------------------------*/
2907 /*-----------------------------------------------------------------*/
2908 int checkLabel(pCode *pc)
2912 if(pc && isPCI(pc)) {
2913 pbr = PCI(pc)->label;
2915 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2925 /*-----------------------------------------------------------------*/
2926 /* findLabelinpBlock - Search the pCode for a particular label */
2927 /*-----------------------------------------------------------------*/
2928 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2935 for(pc = pb->pcHead; pc; pc = pc->next)
2936 if(compareLabel(pc,pcop_label))
2942 /*-----------------------------------------------------------------*/
2943 /* findLabel - Search the pCode for a particular label */
2944 /*-----------------------------------------------------------------*/
2945 pCode * findLabel(pCodeOpLabel *pcop_label)
2953 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2954 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2958 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2962 /*-----------------------------------------------------------------*/
2963 /* findNextpCode - given a pCode, find the next of type 'pct' */
2964 /* in the linked list */
2965 /*-----------------------------------------------------------------*/
2966 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2979 /*-----------------------------------------------------------------*/
2980 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2981 /* in the linked list */
2982 /*-----------------------------------------------------------------*/
2983 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2995 /*-----------------------------------------------------------------*/
2996 /* findNextInstruction - given a pCode, find the next instruction */
2997 /* in the linked list */
2998 /*-----------------------------------------------------------------*/
2999 pCode * findNextInstruction(pCode *pci)
3004 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3008 fprintf(stderr,"findNextInstruction: ");
3009 printpCode(stderr, pc);
3014 //fprintf(stderr,"Couldn't find instruction\n");
3018 /*-----------------------------------------------------------------*/
3019 /* findNextInstruction - given a pCode, find the next instruction */
3020 /* in the linked list */
3021 /*-----------------------------------------------------------------*/
3022 pCode * findPrevInstruction(pCode *pci)
3024 return findPrevpCode(pci, PC_OPCODE);
3027 /*-----------------------------------------------------------------*/
3028 /* findFunctionEnd - given a pCode find the end of the function */
3029 /* that contains it */
3030 /*-----------------------------------------------------------------*/
3031 pCode * findFunctionEnd(pCode *pc)
3035 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3041 fprintf(stderr,"Couldn't find function end\n");
3046 /*-----------------------------------------------------------------*/
3047 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3048 /* instruction with which it is associated. */
3049 /*-----------------------------------------------------------------*/
3050 static void AnalyzeLabel(pCode *pc)
3059 static void AnalyzeGOTO(pCode *pc)
3062 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3066 static void AnalyzeSKIP(pCode *pc)
3069 pBranchLink(pc,findNextInstruction(pc->next));
3070 pBranchLink(pc,findNextInstruction(pc->next->next));
3074 static void AnalyzeRETURN(pCode *pc)
3077 // branch_link(pc,findFunctionEnd(pc->next));
3083 /*-----------------------------------------------------------------*/
3084 /*-----------------------------------------------------------------*/
3085 regs * getRegFromInstruction(pCode *pc)
3090 PCI(pc)->num_ops == 0 )
3093 switch(PCI(pc)->pcop->type) {
3096 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3100 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3101 return PCOR(PCI(pc)->pcop)->r;
3104 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3105 return NULL; // PCOR(PCI(pc)->pcop)->r;
3108 return PCOR(PCI(pc)->pcop)->r;
3111 //fprintf(stderr, "getRegFromInstruction - dir\n");
3112 return PCOR(PCI(pc)->pcop)->r;
3114 //fprintf(stderr, "getRegFromInstruction - literal\n");
3118 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3119 //genericPrint(stderr, pc);
3127 /*-----------------------------------------------------------------*/
3128 /*-----------------------------------------------------------------*/
3130 void AnalyzepBlock(pBlock *pb)
3137 /* Find all of the registers used in this pBlock
3138 * by looking at each instruction and examining it's
3141 for(pc = pb->pcHead; pc; pc = pc->next) {
3143 /* Is this an instruction with operands? */
3144 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3146 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3148 /* Loop through all of the registers declared so far in
3149 this block and see if we find this one there */
3151 regs *r = setFirstItem(pb->tregisters);
3154 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3155 PCOR(PCI(pc)->pcop)->r = r;
3158 r = setNextItem(pb->tregisters);
3162 /* register wasn't found */
3163 r = Safe_calloc(1, sizeof(regs));
3164 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3165 addSet(&pb->tregisters, r);
3166 PCOR(PCI(pc)->pcop)->r = r;
3167 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3169 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3172 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3173 if(PCOR(PCI(pc)->pcop)->r) {
3174 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3175 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3177 if(PCI(pc)->pcop->name)
3178 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3180 fprintf(stderr,"ERROR: NULL register\n");
3189 /*-----------------------------------------------------------------*/
3191 /*-----------------------------------------------------------------*/
3192 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3194 void InsertpFlow(pCode *pc, pCode **pflow)
3196 PCFL(*pflow)->end = pc;
3198 if(!pc || !pc->next)
3201 *pflow = newpCodeFlow();
3202 pCodeInsertAfter(pc, *pflow);
3205 /*-----------------------------------------------------------------*/
3206 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3207 /* the flow blocks. */
3209 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3210 * point the instruction flow changes.
3212 /*-----------------------------------------------------------------*/
3213 void BuildFlow(pBlock *pb)
3216 pCode *last_pci=NULL;
3223 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3224 /* Insert a pCodeFlow object at the beginning of a pBlock */
3226 pflow = newpCodeFlow(); /* Create a new Flow object */
3227 pflow->next = pb->pcHead; /* Make the current head the next object */
3228 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3229 pb->pcHead = pflow; /* Make the Flow object the head */
3232 for( pc = findNextInstruction(pb->pcHead);
3234 pc=findNextInstruction(pc)) {
3237 PCI(pc)->pcflow = PCFL(pflow);
3239 //fprintf(stderr," build: ");
3240 //pflow->print(stderr,pflow);
3242 if( PCI(pc)->isSkip) {
3244 /* The two instructions immediately following this one
3245 * mark the beginning of a new flow segment */
3247 while(pc && PCI(pc)->isSkip) {
3249 PCI(pc)->pcflow = PCFL(pflow);
3253 InsertpFlow(pc, &pflow);
3254 pc=findNextInstruction(pc->next);
3262 PCI(pc)->pcflow = PCFL(pflow);
3264 InsertpFlow(pc, &pflow);
3266 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3268 InsertpFlow(pc, &pflow);
3271 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3273 /* This instruction marks the beginning of a
3274 * new flow segment */
3278 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3280 PCI(pc)->pcflow = PCFL(pflow);
3287 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3288 PCFL(pflow)->end = pb->pcTail;
3291 /*-------------------------------------------------------------------*/
3292 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3293 /* the flow blocks. */
3295 * unBuildFlow removes pCodeFlow objects from a pCode chain
3297 /*-----------------------------------------------------------------*/
3298 void unBuildFlow(pBlock *pb)
3307 pCode *pcn = pc->next;
3311 PCI(pc)->pcflow = NULL;
3313 } else if(isPCFL(pc)) {
3323 /*-----------------------------------------------------------------*/
3324 /*-----------------------------------------------------------------*/
3325 void dumpCond(int cond)
3328 static char *pcc_str[] = {
3342 int ncond = sizeof(pcc_str) / sizeof(char *);
3345 fprintf(stderr, "0x%04X\n",cond);
3347 for(i=0,j=1; i<ncond; i++, j<<=1)
3349 fprintf(stderr, " %s\n",pcc_str[i]);
3353 /*-----------------------------------------------------------------*/
3354 /*-----------------------------------------------------------------*/
3355 void FlowStats(pCodeFlow *pcflow)
3363 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3365 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3368 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3373 fprintf(stderr, " FlowStats inCond: ");
3374 dumpCond(pcflow->inCond);
3375 fprintf(stderr, " FlowStats outCond: ");
3376 dumpCond(pcflow->outCond);
3380 /*-----------------------------------------------------------------*
3381 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3382 * if it affects the banking bits.
3384 * return: -1 == Banking bits are unaffected by this pCode.
3386 * return: > 0 == Banking bits are affected.
3388 * If the banking bits are affected, then the returned value describes
3389 * which bits are affected and how they're affected. The lower half
3390 * of the integer maps to the bits that are affected, the upper half
3391 * to whether they're set or cleared.
3393 *-----------------------------------------------------------------*/
3394 #define SET_BANK_BIT (1 << 16)
3395 #define CLR_BANK_BIT 0
3397 int isBankInstruction(pCode *pc)
3405 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3407 /* Check to see if the register banks are changing */
3408 if(PCI(pc)->isModReg) {
3410 pCodeOp *pcop = PCI(pc)->pcop;
3411 switch(PCI(pc)->op) {
3414 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3415 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3416 return SET_BANK_BIT | PIC_RP0_BIT;
3419 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3420 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3421 return CLR_BANK_BIT | PIC_RP0_BIT;
3426 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3427 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3428 return CLR_BANK_BIT | PIC_RP1_BIT;
3430 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3431 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3432 return CLR_BANK_BIT | PIC_RP1_BIT;
3436 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3437 //genericPrint(stderr, pc);
3448 /*-----------------------------------------------------------------*/
3449 /*-----------------------------------------------------------------*/
3450 void FillFlow(pCodeFlow *pcflow)
3459 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3461 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3464 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3471 isBankInstruction(pc);
3473 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3477 fprintf(stderr, " FillFlow - Bad end of flow\n");
3479 fprintf(stderr, " FillFlow - Ending flow with\n ");
3480 pc->print(stderr,pc);
3483 fprintf(stderr, " FillFlow inCond: ");
3484 dumpCond(pcflow->inCond);
3485 fprintf(stderr, " FillFlow outCond: ");
3486 dumpCond(pcflow->outCond);
3490 /*-----------------------------------------------------------------*/
3491 /*-----------------------------------------------------------------*/
3492 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3494 pCodeFlowLink *fromLink, *toLink;
3496 if(!from || !to || !to->pcflow || !from->pcflow)
3499 fromLink = newpCodeFlowLink(from->pcflow);
3500 toLink = newpCodeFlowLink(to->pcflow);
3502 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3503 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3507 /*-----------------------------------------------------------------*/
3508 /*-----------------------------------------------------------------*/
3509 void LinkFlow(pBlock *pb)
3515 //fprintf(stderr,"linkflow \n");
3517 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3519 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3522 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3524 //fprintf(stderr," link: ");
3525 //pcflow->print(stderr,pcflow);
3527 //FillFlow(PCFL(pcflow));
3529 pc = PCFL(pcflow)->end;
3531 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3532 if(isPCI_SKIP(pc)) {
3533 //fprintf(stderr, "ends with skip\n");
3534 //pc->print(stderr,pc);
3535 pct=findNextInstruction(pc->next);
3536 LinkFlow_pCode(PCI(pc),PCI(pct));
3537 pct=findNextInstruction(pct->next);
3538 LinkFlow_pCode(PCI(pc),PCI(pct));
3542 if(isPCI_BRANCH(pc)) {
3543 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3545 //fprintf(stderr, "ends with branch\n ");
3546 //pc->print(stderr,pc);
3548 if(!(pcol && isPCOLAB(pcol))) {
3549 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3550 pc->print(stderr,pc);
3551 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3556 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3557 LinkFlow_pCode(PCI(pc),PCI(pct));
3559 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3565 //fprintf(stderr, "ends with non-branching instruction:\n");
3566 //pc->print(stderr,pc);
3568 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3574 //fprintf(stderr, "ends with unknown\n");
3575 //pc->print(stderr,pc);
3579 //fprintf(stderr, "ends with nothing: ERROR\n");
3584 /*-----------------------------------------------------------------*/
3585 /*-----------------------------------------------------------------*/
3586 int isPCinFlow(pCode *pc, pCode *pcflow)
3592 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3595 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3601 /*-----------------------------------------------------------------*/
3602 /*-----------------------------------------------------------------*/
3603 void BanksUsedFlow2(pCode *pcflow)
3612 if(!isPCFL(pcflow)) {
3613 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3617 pc = findNextInstruction(pcflow->next);
3619 PCFL(pcflow)->lastBank = -1;
3621 while(isPCinFlow(pc,pcflow)) {
3623 int bank_selected = isBankInstruction(pc);
3625 //if(PCI(pc)->pcflow)
3626 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3628 if(bank_selected > 0) {
3629 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3631 /* This instruction is modifying banking bits before accessing registers */
3633 PCFL(pcflow)->firstBank = -1;
3635 if(PCFL(pcflow)->lastBank == -1)
3636 PCFL(pcflow)->lastBank = 0;
3638 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3639 if(bank_selected & SET_BANK_BIT)
3640 PCFL(pcflow)->lastBank |= bank;
3644 reg = getRegFromInstruction(pc);
3646 if(reg && !isREGinBank(reg, bank)) {
3647 int allbanks = REGallBanks(reg);
3649 PCFL(pcflow)->firstBank = allbanks;
3651 PCFL(pcflow)->lastBank = allbanks;
3658 pc = findNextInstruction(pc->next);
3661 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3662 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3667 /*-----------------------------------------------------------------*/
3668 /*-----------------------------------------------------------------*/
3669 void BanksUsedFlow(pBlock *pb)
3674 //pb->pcHead->print(stderr, pb->pcHead);
3676 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3677 //pcflow->print(stderr,pcflow);
3679 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3681 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3683 BanksUsedFlow2(pcflow);
3689 /*-----------------------------------------------------------------*/
3690 /*-----------------------------------------------------------------*/
3691 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3699 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3701 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3702 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3704 pCodeInsertAfter(pc->prev, new_pc);
3706 /* Move the label, if there is one */
3708 if(PCI(pc)->label) {
3709 PCI(new_pc)->label = PCI(pc)->label;
3710 PCI(pc)->label = NULL;
3713 /* The new instruction has the same pcflow block */
3714 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3717 /*-----------------------------------------------------------------*/
3718 /*-----------------------------------------------------------------*/
3719 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3730 pc = findNextInstruction(pcfl->pc.next);
3732 while(isPCinFlow(pc,PCODE(pcfl))) {
3735 reg = getRegFromInstruction(pc);
3738 fprintf(stderr, " %s ",reg->name);
3739 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3744 if(reg && REG_BANK(reg)!=cur_bank) {
3745 /* Examine the instruction before this one to make sure it is
3746 * not a skip type instruction */
3747 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3748 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3749 int b = cur_bank ^ REG_BANK(reg);
3751 //fprintf(stderr, "Cool! can switch banks\n");
3752 cur_bank = REG_BANK(reg);
3757 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3760 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3761 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3765 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3766 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3768 insertBankSwitch(pc, -1, -1);
3771 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3772 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3773 pCodeInsertAfter(pc->prev, new_pc);
3774 if(PCI(pc)->label) {
3775 PCI(new_pc)->label = PCI(pc)->label;
3776 PCI(pc)->label = NULL;
3780 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3781 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3782 pCodeInsertAfter(pc, new_pc);
3788 //fprintf(stderr, "Bummer can't switch banks\n");
3794 pc = findNextInstruction(pc->next);
3798 if(pcprev && cur_bank) {
3799 /* Brute force - make sure that we point to bank 0 at the
3800 * end of each flow block */
3801 new_pc = newpCode(POC_BCF,
3802 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3803 pCodeInsertAfter(pcprev, new_pc);
3809 /*-----------------------------------------------------------------*/
3810 /*int compareBankFlow - compare the banking requirements between */
3812 /*-----------------------------------------------------------------*/
3813 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3816 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3819 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3822 if(pcflow->firstBank == -1)
3826 if(pcflowLink->pcflow->firstBank == -1) {
3827 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3828 pcflowLink->pcflow->to :
3829 pcflowLink->pcflow->from);
3830 return compareBankFlow(pcflow, pctl, toORfrom);
3834 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3837 pcflowLink->bank_conflict++;
3838 pcflowLink->pcflow->FromConflicts++;
3839 pcflow->ToConflicts++;
3842 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3845 pcflowLink->bank_conflict++;
3846 pcflowLink->pcflow->ToConflicts++;
3847 pcflow->FromConflicts++;
3851 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3852 pcflowLink->pcflow->pc.seq,
3853 pcflowLink->pcflow->FromConflicts,
3854 pcflowLink->pcflow->ToConflicts);
3859 /*-----------------------------------------------------------------*/
3860 /*-----------------------------------------------------------------*/
3861 void FixBankFlow(pBlock *pb)
3865 pCodeFlowLink *pcfl;
3867 pCode *pcflow_max_To=NULL;
3868 pCode *pcflow_max_From=NULL;
3869 int max_ToConflicts=0;
3870 int max_FromConflicts=0;
3872 //fprintf(stderr,"Fix Bank flow \n");
3873 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3877 First loop through all of the flow objects in this pcode block
3878 and fix the ones that have banking conflicts between the
3882 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3884 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3886 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3888 if(!isPCFL(pcflow)) {
3889 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3893 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3894 PCFL(pcflow)->firstBank >= 0 &&
3895 PCFL(pcflow)->lastBank >= 0 ) {
3897 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3898 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3900 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3901 BanksUsedFlow2(pcflow);
3906 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3908 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3910 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3915 if(!isPCFL(pcflow)) {
3916 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3920 PCFL(pcflow)->FromConflicts = 0;
3921 PCFL(pcflow)->ToConflicts = 0;
3926 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3927 pcfl = setFirstItem(PCFL(pcflow)->from);
3930 pc = PCODE(pcfl->pcflow);
3933 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3934 pc->print(stderr,pc);
3937 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3940 pcfl=setNextItem(PCFL(pcflow)->from);
3943 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3944 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3946 FixRegisterBankingInFlow(PCFL(pcflow),0);
3947 BanksUsedFlow2(pcflow);
3949 continue; /* Don't need to check the flow from here - it's already been fixed */
3956 pcfl = setFirstItem(PCFL(pcflow)->to);
3959 pc = PCODE(pcfl->pcflow);
3961 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3962 pc->print(stderr,pc);
3965 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
3968 pcfl=setNextItem(PCFL(pcflow)->to);
3971 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
3972 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3974 FixRegisterBankingInFlow(PCFL(pcflow),0);
3975 BanksUsedFlow2(pcflow);
3980 Loop through the flow objects again and find the ones with the
3984 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3986 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3988 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
3989 pcflow_max_To = pcflow;
3991 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
3992 pcflow_max_From = pcflow;
3996 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
3997 PCFL(pcflow_max_To)->pc.seq,
3998 PCFL(pcflow_max_To)->ToConflicts);
4001 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4002 PCFL(pcflow_max_From)->pc.seq,
4003 PCFL(pcflow_max_From)->FromConflicts);
4007 /*-----------------------------------------------------------------*/
4008 /*-----------------------------------------------------------------*/
4009 void DumpFlow(pBlock *pb)
4013 pCodeFlowLink *pcfl;
4016 fprintf(stderr,"Dump flow \n");
4017 pb->pcHead->print(stderr, pb->pcHead);
4019 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4020 pcflow->print(stderr,pcflow);
4022 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4024 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4026 if(!isPCFL(pcflow)) {
4027 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4030 fprintf(stderr,"dumping: ");
4031 pcflow->print(stderr,pcflow);
4032 FlowStats(PCFL(pcflow));
4034 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4036 pc = PCODE(pcfl->pcflow);
4038 fprintf(stderr, " from seq %d:\n",pc->seq);
4040 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4041 pc->print(stderr,pc);
4046 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4048 pc = PCODE(pcfl->pcflow);
4050 fprintf(stderr, " to seq %d:\n",pc->seq);
4052 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4053 pc->print(stderr,pc);
4062 /*-----------------------------------------------------------------*/
4063 /*-----------------------------------------------------------------*/
4064 int OptimizepBlock(pBlock *pb)
4069 if(!pb || !peepOptimizing)
4072 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4074 for(pc = pb->pcHead; pc; pc = pc->next)
4075 matches += pCodePeepMatchRule(pc);
4078 pc = findNextInstruction(pb->pcHead);
4083 if(pCodePeepMatchRule(pc)) {
4088 pc = findNextInstruction(pcprev->next);
4090 pc = findNextInstruction(pb->pcHead);
4092 pc = findNextInstruction(pc->next);
4096 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4101 /*-----------------------------------------------------------------*/
4102 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4103 /*-----------------------------------------------------------------*/
4104 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4108 for(pc = pcs; pc; pc = pc->next) {
4110 if((pc->type == PC_OPCODE) &&
4112 (PCI(pc)->pcop->type == PO_LABEL) &&
4113 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4121 /*-----------------------------------------------------------------*/
4122 /*-----------------------------------------------------------------*/
4123 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4128 (PCI(pc)->pcop->type == PO_LABEL)) {
4130 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4132 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4134 free(pcol->pcop.name);
4136 sprintf(buffer,"_%05d_DS_",pcl->key);
4138 pcol->pcop.name = Safe_strdup(buffer);
4139 pcol->key = pcl->key;
4140 //pc->print(stderr,pc);
4147 /*-----------------------------------------------------------------*/
4148 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4149 /* pCode chain if they're not used. */
4150 /*-----------------------------------------------------------------*/
4151 void pBlockRemoveUnusedLabels(pBlock *pb)
4153 pCode *pc; pCodeLabel *pcl;
4158 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4160 pBranch *pbr = PCI(pc)->label;
4161 if(pbr && pbr->next) {
4162 pCode *pcd = pb->pcHead;
4164 //fprintf(stderr, "multiple labels\n");
4165 //pc->print(stderr,pc);
4170 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4171 //fprintf(stderr,"Used by:\n");
4172 //pcd->print(stderr,pcd);
4174 exchangeLabels(PCL(pbr->pc),pcd);
4183 for(pc = pb->pcHead; pc; pc = pc->next) {
4185 if(isPCL(pc)) // pc->type == PC_LABEL)
4187 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4188 pcl = PCL(PCI(pc)->label->pc);
4191 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4193 /* This pCode is a label, so search the pBlock to see if anyone
4196 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4197 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4198 /* Couldn't find an instruction that refers to this label
4199 * So, unlink the pCode label from it's pCode chain
4200 * and destroy the label */
4201 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4203 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4204 if(pc->type == PC_LABEL) {
4206 pCodeLabelDestruct(pc);
4208 unlinkpCodeFromBranch(pc, PCODE(pcl));
4209 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4220 /*-----------------------------------------------------------------*/
4221 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4222 /* chain and put them into pBranches that are */
4223 /* associated with the appropriate pCode */
4225 /*-----------------------------------------------------------------*/
4226 void pBlockMergeLabels(pBlock *pb)
4229 pCode *pc, *pcnext=NULL;
4234 /* First, Try to remove any unused labels */
4235 //pBlockRemoveUnusedLabels(pb);
4237 /* Now loop through the pBlock and merge the labels with the opcodes */
4239 for(pc = pb->pcHead; pc; pc = pc->next) {
4241 if(pc->type == PC_LABEL) {
4243 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4244 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4245 if((pcnext = findNextInstruction(pc) )) {
4247 pCode *pcn = pc->next;
4249 // Unlink the pCode label from it's pCode chain
4252 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4253 // And link it into the instruction's pBranch labels. (Note, since
4254 // it's possible to have multiple labels associated with one instruction
4255 // we must provide a means to accomodate the additional labels. Thus
4256 // the labels are placed into the singly-linked list "label" as
4257 // opposed to being a single member of the pCodeInstruction.)
4259 //_ALLOC(pbr,sizeof(pBranch));
4260 pbr = Safe_calloc(1,sizeof(pBranch));
4265 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4270 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4272 } else if(pc->type == PC_CSOURCE) {
4274 /* merge the source line symbolic info into the next instruction */
4275 if((pcnext = findNextInstruction(pc) )) {
4277 pCode *pcn = pc->next;
4279 // Unlink the pCode label from it's pCode chain
4281 PCI(pcnext)->cline = PCCS(pc);
4282 //fprintf(stderr, "merging CSRC\n");
4283 //genericPrint(stderr,pcnext);
4290 pBlockRemoveUnusedLabels(pb);
4294 /*-----------------------------------------------------------------*/
4295 /*-----------------------------------------------------------------*/
4296 int OptimizepCode(char dbName)
4298 #define MAX_PASSES 4
4307 DFPRINTF((stderr," Optimizing pCode\n"));
4311 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4312 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4313 matches += OptimizepBlock(pb);
4316 while(matches && ++passes < MAX_PASSES);
4321 /*-----------------------------------------------------------------*/
4322 /* popCopyGPR2Bit - copy a pcode operator */
4323 /*-----------------------------------------------------------------*/
4325 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4329 pcop = newpCodeOpBit(pc->name, bitval, 0);
4331 if( !( (pcop->type == PO_LABEL) ||
4332 (pcop->type == PO_LITERAL) ||
4333 (pcop->type == PO_STR) ))
4334 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4342 /*-----------------------------------------------------------------*/
4343 /*-----------------------------------------------------------------*/
4344 int InstructionRegBank(pCode *pc)
4348 if( (reg = getRegFromInstruction(pc)) == NULL)
4351 return REG_BANK(reg);
4356 /*-----------------------------------------------------------------*/
4357 /*-----------------------------------------------------------------*/
4358 void FixRegisterBanking(pBlock *pb)
4370 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4371 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4374 /* loop through all of the flow blocks with in one pblock */
4376 //fprintf(stderr,"Register banking\n");
4379 /* at this point, pc should point to a PC_FLOW object */
4382 /* for each flow block, determine the register banking
4387 //genericPrint(stderr, pc);
4389 reg = getRegFromInstruction(pc);
4392 fprintf(stderr, " %s ",reg->name);
4393 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4397 if(reg && REG_BANK(reg)!=cur_bank) {
4398 /* Examine the instruction before this one to make sure it is
4399 * not a skip type instruction */
4400 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4401 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4402 int b = cur_bank ^ REG_BANK(reg);
4404 //fprintf(stderr, "Cool! can switch banks\n");
4405 cur_bank = REG_BANK(reg);
4407 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4408 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4409 pCodeInsertAfter(pc->prev, new_pc);
4410 if(PCI(pc)->label) {
4411 PCI(new_pc)->label = PCI(pc)->label;
4412 PCI(pc)->label = NULL;
4415 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4416 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4417 pCodeInsertAfter(pc, new_pc);
4423 //fprintf(stderr, "Bummer can't switch banks\n");
4431 // } while(pc && !(isPCFL(pc)));
4436 if(pcprev && cur_bank) {
4437 /* Brute force - make sure that we point to bank 0 at the
4438 * end of each flow block */
4439 new_pc = newpCode(POC_BCF,
4440 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4441 pCodeInsertAfter(pcprev, new_pc);
4447 void pBlockDestruct(pBlock *pb)
4458 /*-----------------------------------------------------------------*/
4459 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4460 /* name dbName and combine them */
4461 /* into one block */
4462 /*-----------------------------------------------------------------*/
4463 void mergepBlocks(char dbName)
4466 pBlock *pb, *pbmerged = NULL,*pbn;
4468 pb = the_pFile->pbHead;
4470 //fprintf(stderr," merging blocks named %c\n",dbName);
4474 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4475 if( getpBlock_dbName(pb) == dbName) {
4477 //fprintf(stderr," merged block %c\n",dbName);
4482 addpCode2pBlock(pbmerged, pb->pcHead);
4483 /* addpCode2pBlock doesn't handle the tail: */
4484 pbmerged->pcTail = pb->pcTail;
4486 pb->prev->next = pbn;
4488 pbn->prev = pb->prev;
4493 //printpBlock(stderr, pbmerged);
4500 /*-----------------------------------------------------------------*/
4501 /* AnalyzeBanking - Called after the memory addresses have been */
4502 /* assigned to the registers. */
4504 /*-----------------------------------------------------------------*/
4505 void AnalyzeBanking(void)
4514 /* Phase 2 - Flow Analysis - Register Banking
4516 * In this phase, the individual flow blocks are examined
4517 * and register banking is fixed.
4520 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4521 //FixRegisterBanking(pb);
4523 /* Phase 2 - Flow Analysis
4525 * In this phase, the pCode is partition into pCodeFlow
4526 * blocks. The flow blocks mark the points where a continuous
4527 * stream of instructions changes flow (e.g. because of
4528 * a call or goto or whatever).
4531 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4535 /* Phase 2 - Flow Analysis - linking flow blocks
4537 * In this phase, the individual flow blocks are examined
4538 * to determine their order of excution.
4541 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4545 /* Phase x - Flow Analysis - Used Banks
4547 * In this phase, the individual flow blocks are examined
4548 * to determine the Register Banks they use
4551 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4554 /* Phase x - Flow Analysis - Used Banks
4556 * In this phase, the individual flow blocks are examined
4557 * to determine the Register Banks they use
4560 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4564 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4568 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4570 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4571 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4572 pcflow = pcflow->next) {
4574 FillFlow(PCFL(pcflow));
4578 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4580 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4581 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4582 pcflow = pcflow->next) {
4584 FlowStats(PCFL(pcflow));
4590 /*-----------------------------------------------------------------*/
4591 /* buildCallTree - look at the flow and extract all of the calls */
4593 /*-----------------------------------------------------------------*/
4594 set *register_usage(pBlock *pb);
4596 void buildCallTree(void )
4607 /* Now build the call tree.
4608 First we examine all of the pCodes for functions.
4609 Keep in mind that the function boundaries coincide
4610 with pBlock boundaries.
4612 The algorithm goes something like this:
4613 We have two nested loops. The outer loop iterates
4614 through all of the pBlocks/functions. The inner
4615 loop iterates through all of the pCodes for
4616 a given pBlock. When we begin iterating through
4617 a pBlock, the variable pc_fstart, pCode of the start
4618 of a function, is cleared. We then search for pCodes
4619 of type PC_FUNCTION. When one is encountered, we
4620 initialize pc_fstart to this and at the same time
4621 associate a new pBranch object that signifies a
4622 branch entry. If a return is found, then this signifies
4623 a function exit point. We'll link the pCodes of these
4624 returns to the matching pc_fstart.
4626 When we're done, a doubly linked list of pBranches
4627 will exist. The head of this list is stored in
4628 `the_pFile', which is the meta structure for all
4629 of the pCode. Look at the printCallTree function
4630 on how the pBranches are linked together.
4633 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4634 pCode *pc_fstart=NULL;
4635 for(pc = pb->pcHead; pc; pc = pc->next) {
4637 if (PCF(pc)->fname) {
4639 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4640 //fprintf(stderr," found main \n");
4641 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4645 pbr = Safe_calloc(1,sizeof(pBranch));
4646 pbr->pc = pc_fstart = pc;
4649 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4651 // Here's a better way of doing the same:
4652 addSet(&pb->function_entries, pc);
4655 // Found an exit point in a function, e.g. return
4656 // (Note, there may be more than one return per function)
4658 pBranchLink(PCF(pc_fstart), PCF(pc));
4660 addSet(&pb->function_exits, pc);
4662 } else if(isCALL(pc)) {
4663 addSet(&pb->function_calls,pc);
4668 /* Re-allocate the registers so that there are no collisions
4669 * between local variables when one function call another */
4671 pic14_deallocateAllRegs();
4673 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4680 /*-----------------------------------------------------------------*/
4681 /* AnalyzepCode - parse the pCode that has been generated and form */
4682 /* all of the logical connections. */
4684 /* Essentially what's done here is that the pCode flow is */
4686 /*-----------------------------------------------------------------*/
4688 void AnalyzepCode(char dbName)
4699 /* Phase 1 - Register allocation and peep hole optimization
4701 * The first part of the analysis is to determine the registers
4702 * that are used in the pCode. Once that is done, the peep rules
4703 * are applied to the code. We continue to loop until no more
4704 * peep rule optimizations are found (or until we exceed the
4705 * MAX_PASSES threshold).
4707 * When done, the required registers will be determined.
4713 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4714 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4716 /* First, merge the labels with the instructions */
4717 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4718 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4720 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4721 //fprintf(stderr," analyze and merging block %c\n",dbName);
4722 pBlockMergeLabels(pb);
4725 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4729 changes = OptimizepCode(dbName);
4731 } while(changes && (i++ < MAX_PASSES));
4736 /*-----------------------------------------------------------------*/
4737 /* ispCodeFunction - returns true if *pc is the pCode of a */
4739 /*-----------------------------------------------------------------*/
4740 bool ispCodeFunction(pCode *pc)
4743 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4749 /*-----------------------------------------------------------------*/
4750 /* findFunction - Search for a function by name (given the name) */
4751 /* in the set of all functions that are in a pBlock */
4752 /* (note - I expect this to change because I'm planning to limit */
4753 /* pBlock's to just one function declaration */
4754 /*-----------------------------------------------------------------*/
4755 pCode *findFunction(char *fname)
4762 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4764 pc = setFirstItem(pb->function_entries);
4767 if((pc->type == PC_FUNCTION) &&
4769 (strcmp(fname, PCF(pc)->fname)==0))
4772 pc = setNextItem(pb->function_entries);
4780 void MarkUsedRegisters(set *regset)
4785 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4786 r2 = pic14_regWithIdx(r1->rIdx);
4792 void pBlockStats(FILE *of, pBlock *pb)
4798 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4800 // for now just print the first element of each set
4801 pc = setFirstItem(pb->function_entries);
4803 fprintf(of,";entry: ");
4806 pc = setFirstItem(pb->function_exits);
4808 fprintf(of,";has an exit\n");
4812 pc = setFirstItem(pb->function_calls);
4814 fprintf(of,";functions called:\n");
4817 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4818 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4820 pc = setNextItem(pb->function_calls);
4824 r = setFirstItem(pb->tregisters);
4826 int n = elementsInSet(pb->tregisters);
4828 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4831 fprintf(of,"; %s\n",r->name);
4832 r = setNextItem(pb->tregisters);
4837 /*-----------------------------------------------------------------*/
4838 /*-----------------------------------------------------------------*/
4840 static void sequencepCode(void)
4846 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4848 pb->seq = GpCodeSequenceNumber+1;
4850 for( pc = pb->pcHead; pc; pc = pc->next)
4851 pc->seq = ++GpCodeSequenceNumber;
4857 /*-----------------------------------------------------------------*/
4858 /*-----------------------------------------------------------------*/
4859 set *register_usage(pBlock *pb)
4862 set *registers=NULL;
4863 set *registersInCallPath = NULL;
4865 /* check recursion */
4867 pc = setFirstItem(pb->function_entries);
4874 if(pc->type != PC_FUNCTION)
4875 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4877 pc = setFirstItem(pb->function_calls);
4878 for( ; pc; pc = setNextItem(pb->function_calls)) {
4880 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4881 char *dest = get_op_from_instruction(PCI(pc));
4883 pcn = findFunction(dest);
4885 registersInCallPath = register_usage(pcn->pb);
4887 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4892 pBlockStats(stderr,pb); // debug
4895 // Mark the registers in this block as used.
4897 MarkUsedRegisters(pb->tregisters);
4898 if(registersInCallPath) {
4899 /* registers were used in the functions this pBlock has called */
4900 /* so now, we need to see if these collide with the ones we are */
4903 regs *r1,*r2, *newreg;
4905 DFPRINTF((stderr,"comparing registers\n"));
4907 r1 = setFirstItem(registersInCallPath);
4910 r2 = setFirstItem(pb->tregisters);
4912 while(r2 && (r1->type != REG_STK)) {
4914 if(r2->rIdx == r1->rIdx) {
4915 newreg = pic14_findFreeReg(REG_GPR);
4919 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4923 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4924 r1->rIdx, newreg->rIdx));
4925 r2->rIdx = newreg->rIdx;
4926 //if(r2->name) free(r2->name);
4928 r2->name = Safe_strdup(newreg->name);
4932 newreg->wasUsed = 1;
4934 r2 = setNextItem(pb->tregisters);
4937 r1 = setNextItem(registersInCallPath);
4940 /* Collisions have been resolved. Now free the registers in the call path */
4941 r1 = setFirstItem(registersInCallPath);
4943 if(r1->type != REG_STK) {
4944 newreg = pic14_regWithIdx(r1->rIdx);
4947 r1 = setNextItem(registersInCallPath);
4951 // MarkUsedRegisters(pb->registers);
4953 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4956 DFPRINTF((stderr,"returning regs\n"));
4958 DFPRINTF((stderr,"not returning regs\n"));
4960 DFPRINTF((stderr,"pBlock after register optim.\n"));
4961 pBlockStats(stderr,pb); // debug
4967 /*-----------------------------------------------------------------*/
4968 /* printCallTree - writes the call tree to a file */
4970 /*-----------------------------------------------------------------*/
4971 void pct2(FILE *of,pBlock *pb,int indent)
4975 // set *registersInCallPath = NULL;
4981 return; //recursion ?
4983 pc = setFirstItem(pb->function_entries);
4990 for(i=0;i<indent;i++) // Indentation
4993 if(pc->type == PC_FUNCTION)
4994 fprintf(of,"%s\n",PCF(pc)->fname);
4999 pc = setFirstItem(pb->function_calls);
5000 for( ; pc; pc = setNextItem(pb->function_calls)) {
5002 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5003 char *dest = get_op_from_instruction(PCI(pc));
5005 pcn = findFunction(dest);
5007 pct2(of,pcn->pb,indent+1);
5009 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5017 /*-----------------------------------------------------------------*/
5018 /* printCallTree - writes the call tree to a file */
5020 /*-----------------------------------------------------------------*/
5022 void printCallTree(FILE *of)
5034 fprintf(of, "\npBlock statistics\n");
5035 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5040 fprintf(of,"Call Tree\n");
5041 pbr = the_pFile->functions;
5045 if(!ispCodeFunction(pc))
5046 fprintf(of,"bug in call tree");
5049 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5051 while(pc->next && !ispCodeFunction(pc->next)) {
5053 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5054 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5062 fprintf(of,"\n**************\n\na better call tree\n");
5063 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5068 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5069 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5075 /*-----------------------------------------------------------------*/
5077 /*-----------------------------------------------------------------*/
5079 void InlineFunction(pBlock *pb)
5087 pc = setFirstItem(pb->function_calls);
5089 for( ; pc; pc = setNextItem(pb->function_calls)) {
5092 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5098 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5100 //fprintf(stderr,"Cool can inline:\n");
5101 //pcn->print(stderr,pcn);
5103 //fprintf(stderr,"recursive call Inline\n");
5104 InlineFunction(pcn->pb);
5105 //fprintf(stderr,"return from recursive call Inline\n");
5108 At this point, *pc points to a CALL mnemonic, and
5109 *pcn points to the function that is being called.
5111 To in-line this call, we need to remove the CALL
5112 and RETURN(s), and link the function pCode in with
5118 /* Remove the CALL */
5122 /* remove callee pBlock from the pBlock linked list */
5123 removepBlock(pcn->pb);
5131 /* Remove the Function pCode */
5132 pct = findNextInstruction(pcn->next);
5134 /* Link the function with the callee */
5135 pc->next = pcn->next;
5136 pcn->next->prev = pc;
5138 /* Convert the function name into a label */
5140 pbr = Safe_calloc(1,sizeof(pBranch));
5141 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5143 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5144 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5146 /* turn all of the return's except the last into goto's */
5147 /* check case for 2 instruction pBlocks */
5148 pce = findNextInstruction(pcn->next);
5150 pCode *pce_next = findNextInstruction(pce->next);
5152 if(pce_next == NULL) {
5153 /* found the last return */
5154 pCode *pc_call_next = findNextInstruction(pc_call->next);
5156 //fprintf(stderr,"found last return\n");
5157 //pce->print(stderr,pce);
5158 pce->prev->next = pc_call->next;
5159 pc_call->next->prev = pce->prev;
5160 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5170 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5176 /*-----------------------------------------------------------------*/
5178 /*-----------------------------------------------------------------*/
5180 void InlinepCode(void)
5189 if(!functionInlining)
5192 /* Loop through all of the function definitions and count the
5193 * number of times each one is called */
5194 //fprintf(stderr,"inlining %d\n",__LINE__);
5196 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5198 pc = setFirstItem(pb->function_calls);
5200 for( ; pc; pc = setNextItem(pb->function_calls)) {
5203 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5204 if(pcn && isPCF(pcn)) {
5205 PCF(pcn)->ncalled++;
5208 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5213 //fprintf(stderr,"inlining %d\n",__LINE__);
5215 /* Now, Loop through the function definitions again, but this
5216 * time inline those functions that have only been called once. */
5218 InlineFunction(the_pFile->pbHead);
5219 //fprintf(stderr,"inlining %d\n",__LINE__);
5221 for(pb = the_pFile->pbHead; pb; pb = pb->next)