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 extern void RemoveUnusedRegisters(void);
83 /****************************************************************/
84 /* Forward declarations */
85 /****************************************************************/
87 void unlinkpCode(pCode *pc);
89 static void genericAnalyze(pCode *pc);
90 static void AnalyzeGOTO(pCode *pc);
91 static void AnalyzeSKIP(pCode *pc);
92 static void AnalyzeRETURN(pCode *pc);
95 static void genericDestruct(pCode *pc);
96 static void genericPrint(FILE *of,pCode *pc);
98 static void pCodePrintLabel(FILE *of, pCode *pc);
99 static void pCodePrintFunction(FILE *of, pCode *pc);
100 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
101 static char *get_op_from_instruction( pCodeInstruction *pcc);
102 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
103 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
104 int pCodePeepMatchRule(pCode *pc);
105 void pBlockStats(FILE *of, pBlock *pb);
106 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
107 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
108 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
109 void pCodeRegMapLiveRanges(pBlock *pb);
112 /****************************************************************/
113 /* PIC Instructions */
114 /****************************************************************/
116 pCodeInstruction pciADDWF = {
117 {PC_OPCODE, NULL, NULL, 0, NULL,
130 1,0, // dest, bit instruction
133 (PCC_W | PCC_REGISTER), // inCond
134 (PCC_REGISTER | PCC_Z) // outCond
137 pCodeInstruction pciADDFW = {
138 {PC_OPCODE, NULL, NULL, 0, NULL,
151 0,0, // dest, bit instruction
154 (PCC_W | PCC_REGISTER), // inCond
155 (PCC_W | PCC_Z) // outCond
158 pCodeInstruction pciADDLW = {
159 {PC_OPCODE, NULL, NULL, 0, NULL,
172 0,0, // dest, bit instruction
176 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
179 pCodeInstruction pciANDLW = {
180 {PC_OPCODE, NULL, NULL, 0, NULL,
193 0,0, // dest, bit instruction
197 (PCC_W | PCC_Z) // outCond
200 pCodeInstruction pciANDWF = {
201 {PC_OPCODE, NULL, NULL, 0, NULL,
214 1,0, // dest, bit instruction
217 (PCC_W | PCC_REGISTER), // inCond
218 (PCC_REGISTER | PCC_Z) // outCond
221 pCodeInstruction pciANDFW = {
222 {PC_OPCODE, NULL, NULL, 0, NULL,
235 0,0, // dest, bit instruction
238 (PCC_W | PCC_REGISTER), // inCond
239 (PCC_W | PCC_Z) // outCond
242 pCodeInstruction pciBCF = {
243 {PC_OPCODE, NULL, NULL, 0, NULL,
256 1,1, // dest, bit instruction
259 PCC_REGISTER, // inCond
260 PCC_REGISTER // outCond
263 pCodeInstruction pciBSF = {
264 {PC_OPCODE, NULL, NULL, 0, NULL,
277 1,1, // dest, bit instruction
280 PCC_REGISTER, // inCond
281 PCC_REGISTER // outCond
284 pCodeInstruction pciBTFSC = {
285 {PC_OPCODE, NULL, NULL, 0, NULL,
298 0,1, // dest, bit instruction
301 PCC_REGISTER, // inCond
305 pCodeInstruction pciBTFSS = {
306 {PC_OPCODE, NULL, NULL, 0, NULL,
319 0,1, // dest, bit instruction
322 PCC_REGISTER, // inCond
326 pCodeInstruction pciCALL = {
327 {PC_OPCODE, NULL, NULL, 0, NULL,
340 0,0, // dest, bit instruction
347 pCodeInstruction pciCOMF = {
348 {PC_OPCODE, NULL, NULL, 0, NULL,
361 1,0, // dest, bit instruction
364 PCC_REGISTER, // inCond
365 PCC_REGISTER // outCond
368 pCodeInstruction pciCOMFW = {
369 {PC_OPCODE, NULL, NULL, 0, NULL,
382 0,0, // dest, bit instruction
385 PCC_REGISTER, // inCond
389 pCodeInstruction pciCLRF = {
390 {PC_OPCODE, NULL, NULL, 0, NULL,
403 0,0, // dest, bit instruction
407 PCC_REGISTER // outCond
410 pCodeInstruction pciCLRW = {
411 {PC_OPCODE, NULL, NULL, 0, NULL,
424 0,0, // dest, bit instruction
431 pCodeInstruction pciDECF = {
432 {PC_OPCODE, NULL, NULL, 0, NULL,
445 1,0, // dest, bit instruction
448 PCC_REGISTER, // inCond
449 PCC_REGISTER // outCond
452 pCodeInstruction pciDECFW = {
453 {PC_OPCODE, NULL, NULL, 0, NULL,
466 0,0, // dest, bit instruction
469 PCC_REGISTER, // inCond
473 pCodeInstruction pciDECFSZ = {
474 {PC_OPCODE, NULL, NULL, 0, NULL,
487 1,0, // dest, bit instruction
490 PCC_REGISTER, // inCond
491 PCC_REGISTER // outCond
494 pCodeInstruction pciDECFSZW = {
495 {PC_OPCODE, NULL, NULL, 0, NULL,
508 0,0, // dest, bit instruction
511 PCC_REGISTER, // inCond
515 pCodeInstruction pciGOTO = {
516 {PC_OPCODE, NULL, NULL, 0, NULL,
529 0,0, // dest, bit instruction
536 pCodeInstruction pciINCF = {
537 {PC_OPCODE, NULL, NULL, 0, NULL,
550 1,0, // dest, bit instruction
553 PCC_REGISTER, // inCond
554 PCC_REGISTER // outCond
557 pCodeInstruction pciINCFW = {
558 {PC_OPCODE, NULL, NULL, 0, NULL,
571 0,0, // dest, bit instruction
574 PCC_REGISTER, // inCond
578 pCodeInstruction pciINCFSZ = {
579 {PC_OPCODE, NULL, NULL, 0, NULL,
592 1,0, // dest, bit instruction
595 PCC_REGISTER, // inCond
596 PCC_REGISTER // outCond
599 pCodeInstruction pciINCFSZW = {
600 {PC_OPCODE, NULL, NULL, 0, NULL,
613 0,0, // dest, bit instruction
616 PCC_REGISTER, // inCond
620 pCodeInstruction pciIORWF = {
621 {PC_OPCODE, NULL, NULL, 0, NULL,
634 1,0, // dest, bit instruction
637 (PCC_W | PCC_REGISTER), // inCond
638 (PCC_REGISTER | PCC_Z) // outCond
641 pCodeInstruction pciIORFW = {
642 {PC_OPCODE, NULL, NULL, 0, NULL,
655 0,0, // dest, bit instruction
658 (PCC_W | PCC_REGISTER), // inCond
659 (PCC_W | PCC_Z) // outCond
662 pCodeInstruction pciIORLW = {
663 {PC_OPCODE, NULL, NULL, 0, NULL,
676 0,0, // dest, bit instruction
680 (PCC_W | PCC_Z) // outCond
683 pCodeInstruction pciMOVF = {
684 {PC_OPCODE, NULL, NULL, 0, NULL,
697 1,0, // dest, bit instruction
700 PCC_REGISTER, // inCond
704 pCodeInstruction pciMOVFW = {
705 {PC_OPCODE, NULL, NULL, 0, NULL,
718 0,0, // dest, bit instruction
721 PCC_REGISTER, // inCond
722 (PCC_W | PCC_Z) // outCond
725 pCodeInstruction pciMOVWF = {
726 {PC_OPCODE, NULL, NULL, 0, NULL,
739 0,0, // dest, bit instruction
743 PCC_REGISTER // outCond
746 pCodeInstruction pciMOVLW = {
747 {PC_OPCODE, NULL, NULL, 0, NULL,
760 0,0, // dest, bit instruction
767 pCodeInstruction pciNOP = {
768 {PC_OPCODE, NULL, NULL, 0, NULL,
780 0,0, // dest, bit instruction
787 pCodeInstruction pciRETFIE = {
788 {PC_OPCODE, NULL, NULL, 0, NULL,
801 0,0, // dest, bit instruction
805 PCC_NONE // outCond (not true... affects the GIE bit too)
808 pCodeInstruction pciRETLW = {
809 {PC_OPCODE, NULL, NULL, 0, NULL,
822 0,0, // dest, bit instruction
829 pCodeInstruction pciRETURN = {
830 {PC_OPCODE, NULL, NULL, 0, NULL,
843 0,0, // dest, bit instruction
850 pCodeInstruction pciRLF = {
851 {PC_OPCODE, NULL, NULL, 0, NULL,
864 1,0, // dest, bit instruction
867 (PCC_C | PCC_REGISTER), // inCond
868 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
871 pCodeInstruction pciRLFW = {
872 {PC_OPCODE, NULL, NULL, 0, NULL,
885 0,0, // dest, bit instruction
888 (PCC_C | PCC_REGISTER), // inCond
889 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
892 pCodeInstruction pciRRF = {
893 {PC_OPCODE, NULL, NULL, 0, NULL,
906 1,0, // dest, bit instruction
909 (PCC_C | PCC_REGISTER), // inCond
910 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
913 pCodeInstruction pciRRFW = {
914 {PC_OPCODE, NULL, NULL, 0, NULL,
927 0,0, // dest, bit instruction
930 (PCC_C | PCC_REGISTER), // inCond
931 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
934 pCodeInstruction pciSUBWF = {
935 {PC_OPCODE, NULL, NULL, 0, NULL,
948 1,0, // dest, bit instruction
951 (PCC_W | PCC_REGISTER), // inCond
952 (PCC_REGISTER | PCC_Z) // outCond
955 pCodeInstruction pciSUBFW = {
956 {PC_OPCODE, NULL, NULL, 0, NULL,
969 0,0, // dest, bit instruction
972 (PCC_W | PCC_REGISTER), // inCond
973 (PCC_W | PCC_Z) // outCond
976 pCodeInstruction pciSUBLW = {
977 {PC_OPCODE, NULL, NULL, 0, NULL,
990 0,0, // dest, bit instruction
994 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
997 pCodeInstruction pciSWAPF = {
998 {PC_OPCODE, NULL, NULL, 0, NULL,
1004 NULL, // from branch
1011 1,0, // dest, bit instruction
1012 0,0, // branch, skip
1014 (PCC_REGISTER), // inCond
1015 (PCC_REGISTER) // outCond
1018 pCodeInstruction pciSWAPFW = {
1019 {PC_OPCODE, NULL, NULL, 0, NULL,
1025 NULL, // from branch
1032 0,0, // dest, bit instruction
1033 0,0, // branch, skip
1035 (PCC_REGISTER), // inCond
1039 pCodeInstruction pciTRIS = {
1040 {PC_OPCODE, NULL, NULL, 0, NULL,
1046 NULL, // from branch
1053 0,0, // dest, bit instruction
1054 0,0, // branch, skip
1057 PCC_REGISTER // outCond
1060 pCodeInstruction pciXORWF = {
1061 {PC_OPCODE, NULL, NULL, 0, NULL,
1067 NULL, // from branch
1074 1,0, // dest, bit instruction
1075 0,0, // branch, skip
1077 (PCC_W | PCC_REGISTER), // inCond
1078 (PCC_REGISTER | PCC_Z) // outCond
1081 pCodeInstruction pciXORFW = {
1082 {PC_OPCODE, NULL, NULL, 0, NULL,
1088 NULL, // from branch
1095 0,0, // dest, bit instruction
1096 0,0, // branch, skip
1098 (PCC_W | PCC_REGISTER), // inCond
1099 (PCC_W | PCC_Z) // outCond
1102 pCodeInstruction pciXORLW = {
1103 {PC_OPCODE, NULL, NULL, 0, NULL,
1109 NULL, // from branch
1116 0,0, // dest, bit instruction
1117 0,0, // branch, skip
1120 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1124 #define MAX_PIC14MNEMONICS 100
1125 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1127 /* This definition needs to be part of configure.in */
1128 // #define USE_VSNPRINTF
1130 #ifdef USE_VSNPRINTF
1131 // Alas, vsnprintf is not ANSI standard, and does not exist
1132 // on Solaris (and probably other non-Gnu flavored Unixes).
1134 /*-----------------------------------------------------------------*/
1135 /* SAFE_snprintf - like snprintf except the string pointer is */
1136 /* after the string has been printed to. This is */
1137 /* useful for printing to string as though if it */
1138 /* were a stream. */
1139 /*-----------------------------------------------------------------*/
1140 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1148 va_start(val, format);
1150 vsnprintf(*str, *size, format, val);
1156 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1157 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1165 #else // USE_VSNPRINTF
1167 // This version is *not* safe, despite the name.
1169 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1173 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1178 va_start(val, format);
1180 vsprintf(buffer, format, val);
1183 len = strlen(buffer);
1185 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1186 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1189 strcpy(*str, buffer);
1195 #endif // USE_VSNPRINTF
1198 extern void initStack(int base_address, int size);
1199 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1200 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1201 extern void init_pic(char *);
1203 void pCodeInitRegisters(void)
1206 initStack(0xfff, 8);
1207 init_pic(port->processor);
1209 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1210 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1211 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1212 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1213 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1214 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1216 pc_status.rIdx = IDX_STATUS;
1217 pc_fsr.rIdx = IDX_FSR;
1218 pc_indf.rIdx = IDX_INDF;
1219 pc_intcon.rIdx = IDX_INTCON;
1220 pc_pcl.rIdx = IDX_PCL;
1221 pc_pclath.rIdx = IDX_PCLATH;
1223 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1224 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1225 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1227 pc_kzero.rIdx = IDX_KZ;
1228 pc_wsave.rIdx = IDX_WSAVE;
1229 pc_ssave.rIdx = IDX_SSAVE;
1233 /*-----------------------------------------------------------------*/
1234 /* mnem2key - convert a pic mnemonic into a hash key */
1235 /* (BTW - this spreads the mnemonics quite well) */
1237 /*-----------------------------------------------------------------*/
1239 int mnem2key(char const *mnem)
1248 key += toupper(*mnem++) +1;
1252 return (key & 0x1f);
1256 void pic14initMnemonics(void)
1261 pCodeInstruction *pci;
1263 if(mnemonics_initialized)
1266 //FIXME - probably should NULL out the array before making the assignments
1267 //since we check the array contents below this initialization.
1269 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1270 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1271 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1272 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1273 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1274 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1275 pic14Mnemonics[POC_BCF] = &pciBCF;
1276 pic14Mnemonics[POC_BSF] = &pciBSF;
1277 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1278 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1279 pic14Mnemonics[POC_CALL] = &pciCALL;
1280 pic14Mnemonics[POC_COMF] = &pciCOMF;
1281 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1282 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1283 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1284 pic14Mnemonics[POC_DECF] = &pciDECF;
1285 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1286 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1287 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1288 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1289 pic14Mnemonics[POC_INCF] = &pciINCF;
1290 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1291 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1292 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1293 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1294 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1295 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1296 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1297 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1298 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1299 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1300 pic14Mnemonics[POC_NOP] = &pciNOP;
1301 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1302 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1303 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1304 pic14Mnemonics[POC_RLF] = &pciRLF;
1305 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1306 pic14Mnemonics[POC_RRF] = &pciRRF;
1307 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1308 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1309 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1310 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1311 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1312 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1313 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1314 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1315 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1316 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1318 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1319 if(pic14Mnemonics[i])
1320 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1321 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1324 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1325 pci = hTabNextItem(pic14MnemonicsHash, &key);
1328 mnemonics_initialized = 1;
1331 int getpCodePeepCommand(char *cmd);
1333 int getpCode(char *mnem,unsigned dest)
1336 pCodeInstruction *pci;
1337 int key = mnem2key(mnem);
1339 if(!mnemonics_initialized)
1340 pic14initMnemonics();
1342 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1346 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1347 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1351 pci = hTabNextItemWK (pic14MnemonicsHash);
1358 /*-----------------------------------------------------------------*
1359 * pic14initpCodePeepCommands
1361 *-----------------------------------------------------------------*/
1362 void pic14initpCodePeepCommands(void)
1370 hTabAddItem(&pic14pCodePeepCommandsHash,
1371 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1373 } while (peepCommands[i].cmd);
1375 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1378 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1379 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1384 /*-----------------------------------------------------------------
1387 *-----------------------------------------------------------------*/
1389 int getpCodePeepCommand(char *cmd)
1393 int key = mnem2key(cmd);
1396 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1399 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1400 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1404 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1411 char getpBlock_dbName(pBlock *pb)
1417 return pb->cmemmap->dbName;
1421 void pBlockConvert2ISR(pBlock *pb)
1432 /*-----------------------------------------------------------------*/
1433 /* movepBlock2Head - given the dbname of a pBlock, move all */
1434 /* instances to the front of the doubly linked */
1435 /* list of pBlocks */
1436 /*-----------------------------------------------------------------*/
1438 void movepBlock2Head(char dbName)
1442 pb = the_pFile->pbHead;
1446 if(getpBlock_dbName(pb) == dbName) {
1447 pBlock *pbn = pb->next;
1448 pb->next = the_pFile->pbHead;
1449 the_pFile->pbHead->prev = pb;
1450 the_pFile->pbHead = pb;
1453 pb->prev->next = pbn;
1455 // If the pBlock that we just moved was the last
1456 // one in the link of all of the pBlocks, then we
1457 // need to point the tail to the block just before
1458 // the one we moved.
1459 // Note: if pb->next is NULL, then pb must have
1460 // been the last pBlock in the chain.
1463 pbn->prev = pb->prev;
1465 the_pFile->pbTail = pb->prev;
1476 void copypCode(FILE *of, char dbName)
1480 if(!of || !the_pFile)
1483 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1484 if(getpBlock_dbName(pb) == dbName) {
1491 void pcode_test(void)
1494 DFPRINTF((stderr,"pcode is alive!\n"));
1504 /* create the file name */
1505 strcpy(buffer,srcFileName);
1506 strcat(buffer,".p");
1508 if( !(pFile = fopen(buffer, "w" ))) {
1509 werror(E_FILE_OPEN_ERR,buffer);
1513 fprintf(pFile,"pcode dump\n\n");
1515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1516 fprintf(pFile,"\n\tNew pBlock\n\n");
1518 fprintf(pFile,"%s",pb->cmemmap->sname);
1520 fprintf(pFile,"internal pblock");
1522 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1523 printpBlock(pFile,pb);
1527 /*-----------------------------------------------------------------*/
1528 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1529 /* ister, RegCond will return the bit being referenced. */
1531 /* fixme - why not just OR in the pcop bit field */
1532 /*-----------------------------------------------------------------*/
1534 static int RegCond(pCodeOp *pcop)
1540 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1541 switch(PCORB(pcop)->bit) {
1555 /*-----------------------------------------------------------------*/
1556 /* newpCode - create and return a newly initialized pCode */
1558 /* fixme - rename this */
1560 /* The purpose of this routine is to create a new Instruction */
1561 /* pCode. This is called by gen.c while the assembly code is being */
1565 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1566 /* (note that the op is analogous to but not the */
1567 /* same thing as the opcode of the instruction.) */
1568 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1571 /* a pointer to the new malloc'd pCode is returned. */
1575 /*-----------------------------------------------------------------*/
1576 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1578 pCodeInstruction *pci ;
1580 if(!mnemonics_initialized)
1581 pic14initMnemonics();
1583 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1585 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1586 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1589 if(pci->inCond == PCC_EXAMINE_PCOP)
1590 pci->inCond = RegCond(pcop);
1592 if(pci->outCond == PCC_EXAMINE_PCOP)
1593 pci->outCond = RegCond(pcop);
1595 pci->pc.prev = pci->pc.next = NULL;
1596 return (pCode *)pci;
1599 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1605 /*-----------------------------------------------------------------*/
1606 /* newpCodeWild - create a "wild" as in wild card pCode */
1608 /* Wild pcodes are used during the peep hole optimizer to serve */
1609 /* as place holders for any instruction. When a snippet of code is */
1610 /* compared to a peep hole rule, the wild card opcode will match */
1611 /* any instruction. However, the optional operand and label are */
1612 /* additional qualifiers that must also be matched before the */
1613 /* line (of assembly code) is declared matched. Note that the */
1614 /* operand may be wild too. */
1616 /* Note, a wild instruction is specified just like a wild var: */
1617 /* %4 ; A wild instruction, */
1618 /* See the peeph.def file for additional examples */
1620 /*-----------------------------------------------------------------*/
1622 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1627 pcw = Safe_calloc(1,sizeof(pCodeWild));
1629 pcw->pci.pc.type = PC_WILD;
1630 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1631 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1632 pcw->pci.pc.pb = NULL;
1634 // pcw->pci.pc.analyze = genericAnalyze;
1635 pcw->pci.pc.destruct = genericDestruct;
1636 pcw->pci.pc.print = genericPrint;
1638 pcw->id = pCodeID; // this is the 'n' in %n
1639 pcw->operand = optional_operand;
1640 pcw->label = optional_label;
1642 pcw->mustBeBitSkipInst = 0;
1643 pcw->mustNotBeBitSkipInst = 0;
1644 pcw->invertBitSkipInst = 0;
1646 return ( (pCode *)pcw);
1650 /*-----------------------------------------------------------------*/
1651 /* newPcodeInlineP - create a new pCode from a char string */
1652 /*-----------------------------------------------------------------*/
1655 pCode *newpCodeInlineP(char *cP)
1660 pcc = Safe_calloc(1,sizeof(pCodeComment));
1662 pcc->pc.type = PC_INLINE;
1663 pcc->pc.prev = pcc->pc.next = NULL;
1664 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1667 // pcc->pc.analyze = genericAnalyze;
1668 pcc->pc.destruct = genericDestruct;
1669 pcc->pc.print = genericPrint;
1672 pcc->comment = Safe_strdup(cP);
1674 pcc->comment = NULL;
1676 return ( (pCode *)pcc);
1680 /*-----------------------------------------------------------------*/
1681 /* newPcodeCharP - create a new pCode from a char string */
1682 /*-----------------------------------------------------------------*/
1684 pCode *newpCodeCharP(char *cP)
1689 pcc = Safe_calloc(1,sizeof(pCodeComment));
1691 pcc->pc.type = PC_COMMENT;
1692 pcc->pc.prev = pcc->pc.next = NULL;
1693 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1696 // pcc->pc.analyze = genericAnalyze;
1697 pcc->pc.destruct = genericDestruct;
1698 pcc->pc.print = genericPrint;
1701 pcc->comment = Safe_strdup(cP);
1703 pcc->comment = NULL;
1705 return ( (pCode *)pcc);
1709 /*-----------------------------------------------------------------*/
1710 /* newpCodeFunction - */
1711 /*-----------------------------------------------------------------*/
1714 pCode *newpCodeFunction(char *mod,char *f)
1718 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1719 //_ALLOC(pcf,sizeof(pCodeFunction));
1721 pcf->pc.type = PC_FUNCTION;
1722 pcf->pc.prev = pcf->pc.next = NULL;
1723 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1726 // pcf->pc.analyze = genericAnalyze;
1727 pcf->pc.destruct = genericDestruct;
1728 pcf->pc.print = pCodePrintFunction;
1733 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1734 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1735 strcpy(pcf->modname,mod);
1737 pcf->modname = NULL;
1740 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1741 pcf->fname = Safe_calloc(1,strlen(f)+1);
1742 strcpy(pcf->fname,f);
1746 return ( (pCode *)pcf);
1750 /*-----------------------------------------------------------------*/
1752 /*-----------------------------------------------------------------*/
1754 void destructpCodeFlow(pCode *pc)
1756 if(!pc || !isPCFL(pc))
1760 free(PCFL(pc)->uses);
1768 pCode *newpCodeFlow(void )
1772 //_ALLOC(pcflow,sizeof(pCodeFlow));
1773 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1775 pcflow->pc.type = PC_FLOW;
1776 pcflow->pc.prev = pcflow->pc.next = NULL;
1777 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1778 pcflow->pc.pb = NULL;
1780 // pcflow->pc.analyze = genericAnalyze;
1781 pcflow->pc.destruct = destructpCodeFlow;
1782 pcflow->pc.print = genericPrint;
1784 pcflow->pc.seq = GpcFlowSeq++;
1787 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1789 pcflow->from = pcflow->to = NULL;
1791 pcflow->inCond = PCC_NONE;
1792 pcflow->outCond = PCC_NONE;
1794 pcflow->firstBank = -1;
1795 pcflow->lastBank = -1;
1797 pcflow->FromConflicts = 0;
1798 pcflow->ToConflicts = 0;
1802 pcflow->registers = newSet();
1804 return ( (pCode *)pcflow);
1808 /*-----------------------------------------------------------------*/
1809 /*-----------------------------------------------------------------*/
1810 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1812 pCodeFlowLink *pcflowLink;
1814 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1816 pcflowLink->pcflow = pcflow;
1817 pcflowLink->bank_conflict = 0;
1822 /*-----------------------------------------------------------------*/
1823 /* newpCodeCSource - create a new pCode Source Symbol */
1824 /*-----------------------------------------------------------------*/
1826 pCode *newpCodeCSource(int ln, char *f, char *l)
1831 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1833 pccs->pc.type = PC_CSOURCE;
1834 pccs->pc.prev = pccs->pc.next = NULL;
1837 pccs->pc.destruct = genericDestruct;
1838 pccs->pc.print = genericPrint;
1840 pccs->line_number = ln;
1842 pccs->line = Safe_strdup(l);
1847 pccs->file_name = Safe_strdup(f);
1849 pccs->file_name = NULL;
1851 return ( (pCode *)pccs);
1854 /*-----------------------------------------------------------------*/
1855 /* pCodeLabelDestruct - free memory used by a label. */
1856 /*-----------------------------------------------------------------*/
1857 static void pCodeLabelDestruct(pCode *pc)
1863 if((pc->type == PC_LABEL) && PCL(pc)->label)
1864 free(PCL(pc)->label);
1870 pCode *newpCodeLabel(char *name, int key)
1876 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1878 pcl->pc.type = PC_LABEL;
1879 pcl->pc.prev = pcl->pc.next = NULL;
1880 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1883 // pcl->pc.analyze = genericAnalyze;
1884 pcl->pc.destruct = pCodeLabelDestruct;
1885 pcl->pc.print = pCodePrintLabel;
1891 sprintf(s,"_%05d_DS_",key);
1896 pcl->label = Safe_strdup(s);
1899 return ( (pCode *)pcl);
1904 /*-----------------------------------------------------------------*/
1905 /* newpBlock - create and return a pointer to a new pBlock */
1906 /*-----------------------------------------------------------------*/
1907 pBlock *newpBlock(void)
1912 PpB = Safe_calloc(1,sizeof(pBlock) );
1913 PpB->next = PpB->prev = NULL;
1915 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1916 PpB->tregisters = NULL;
1923 /*-----------------------------------------------------------------*/
1924 /* newpCodeChain - create a new chain of pCodes */
1925 /*-----------------------------------------------------------------*
1927 * This function will create a new pBlock and the pointer to the
1928 * pCode that is passed in will be the first pCode in the block.
1929 *-----------------------------------------------------------------*/
1932 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1935 pBlock *pB = newpBlock();
1937 pB->pcHead = pB->pcTail = pc;
1944 /*-----------------------------------------------------------------*/
1945 /* newpCodeOpLabel - Create a new label given the key */
1946 /* Note, a negative key means that the label is part of wild card */
1947 /* (and hence a wild card label) used in the pCodePeep */
1948 /* optimizations). */
1949 /*-----------------------------------------------------------------*/
1951 pCodeOp *newpCodeOpLabel(char *name, int key)
1954 static int label_key=-1;
1958 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1959 pcop->type = PO_LABEL;
1964 sprintf(s=buffer,"_%05d_DS_",key);
1966 s = name, key = label_key--;
1969 pcop->name = Safe_strdup(s);
1971 ((pCodeOpLabel *)pcop)->key = key;
1976 /*-----------------------------------------------------------------*/
1977 /*-----------------------------------------------------------------*/
1978 pCodeOp *newpCodeOpLit(int lit)
1984 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1985 pcop->type = PO_LITERAL;
1989 sprintf(s,"0x%02x",lit);
1991 pcop->name = Safe_strdup(s);
1994 ((pCodeOpLit *)pcop)->lit = lit;
1999 /*-----------------------------------------------------------------*/
2000 /*-----------------------------------------------------------------*/
2001 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2005 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2006 pcop->type = PO_IMMEDIATE;
2008 pcop->name = Safe_strdup(name);
2009 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2015 PCOI(pcop)->index = index;
2016 PCOI(pcop)->offset = offset;
2017 PCOI(pcop)->_const = code_space;
2022 /*-----------------------------------------------------------------*/
2023 /*-----------------------------------------------------------------*/
2024 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2030 if(!pcwb || !subtype) {
2031 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2035 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2036 pcop->type = PO_WILD;
2037 sprintf(s,"%%%d",id);
2038 pcop->name = Safe_strdup(s);
2040 PCOW(pcop)->id = id;
2041 PCOW(pcop)->pcwb = pcwb;
2042 PCOW(pcop)->subtype = subtype;
2043 PCOW(pcop)->matched = NULL;
2048 /*-----------------------------------------------------------------*/
2049 /*-----------------------------------------------------------------*/
2050 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2054 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2055 pcop->type = PO_GPR_BIT;
2057 pcop->name = Safe_strdup(s);
2061 PCORB(pcop)->bit = bit;
2062 PCORB(pcop)->inBitSpace = inBitSpace;
2067 /*-----------------------------------------------------------------*
2068 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2070 * If rIdx >=0 then a specific register from the set of registers
2071 * will be selected. If rIdx <0, then a new register will be searched
2073 *-----------------------------------------------------------------*/
2075 pCodeOp *newpCodeOpReg(int rIdx)
2079 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2084 PCOR(pcop)->rIdx = rIdx;
2085 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2087 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2090 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2091 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2094 pcop->type = PCOR(pcop)->r->pc_type;
2099 pCodeOp *newpCodeOpRegFromStr(char *name)
2103 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2104 PCOR(pcop)->r = allocRegByName(name, 1);
2105 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2106 pcop->type = PCOR(pcop)->r->pc_type;
2107 pcop->name = PCOR(pcop)->r->name;
2112 /*-----------------------------------------------------------------*/
2113 /*-----------------------------------------------------------------*/
2115 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2122 pcop = newpCodeOpBit(name, -1,0);
2126 pcop = newpCodeOpLit(-1);
2130 pcop = newpCodeOpLabel(NULL,-1);
2133 pcop = newpCodeOpReg(-1);
2137 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2140 pcop->name = Safe_strdup(name);
2148 /*-----------------------------------------------------------------*/
2149 /*-----------------------------------------------------------------*/
2150 void pCodeConstString(char *name, char *value)
2154 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2159 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2163 sprintf(buffer,"; %s = %s",name,value);
2165 addpCode2pBlock(pb,newpCodeCharP(buffer));
2166 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2169 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2175 /*-----------------------------------------------------------------*/
2176 /*-----------------------------------------------------------------*/
2177 void pCodeReadCodeTable(void)
2181 fprintf(stderr, " %s\n",__FUNCTION__);
2183 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2187 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2188 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2189 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2190 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2192 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2193 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2194 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2195 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2200 /*-----------------------------------------------------------------*/
2201 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2202 /*-----------------------------------------------------------------*/
2203 void addpCode2pBlock(pBlock *pb, pCode *pc)
2206 /* If this is the first pcode to be added to a block that
2207 * was initialized with a NULL pcode, then go ahead and
2208 * make this pcode the head and tail */
2209 pb->pcHead = pb->pcTail = pc;
2211 pb->pcTail->next = pc;
2212 pc->prev = pb->pcTail;
2219 /*-----------------------------------------------------------------*/
2220 /* addpBlock - place a pBlock into the pFile */
2221 /*-----------------------------------------------------------------*/
2222 void addpBlock(pBlock *pb)
2224 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2227 /* First time called, we'll pass through here. */
2228 //_ALLOC(the_pFile,sizeof(pFile));
2229 the_pFile = Safe_calloc(1,sizeof(pFile));
2230 the_pFile->pbHead = the_pFile->pbTail = pb;
2231 the_pFile->functions = NULL;
2235 the_pFile->pbTail->next = pb;
2236 pb->prev = the_pFile->pbTail;
2238 the_pFile->pbTail = pb;
2241 /*-----------------------------------------------------------------*/
2242 /* removepBlock - remove a pBlock from the pFile */
2243 /*-----------------------------------------------------------------*/
2244 void removepBlock(pBlock *pb)
2252 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2254 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2257 if(pbs == the_pFile->pbHead)
2258 the_pFile->pbHead = pbs->next;
2260 if (pbs == the_pFile->pbTail)
2261 the_pFile->pbTail = pbs->prev;
2264 pbs->next->prev = pbs->prev;
2267 pbs->prev->next = pbs->next;
2274 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2278 /*-----------------------------------------------------------------*/
2279 /* printpCode - write the contents of a pCode to a file */
2280 /*-----------------------------------------------------------------*/
2281 void printpCode(FILE *of, pCode *pc)
2292 fprintf(of,"warning - unable to print pCode\n");
2295 /*-----------------------------------------------------------------*/
2296 /* printpBlock - write the contents of a pBlock to a file */
2297 /*-----------------------------------------------------------------*/
2298 void printpBlock(FILE *of, pBlock *pb)
2308 for(pc = pb->pcHead; pc; pc = pc->next)
2313 /*-----------------------------------------------------------------*/
2315 /* pCode processing */
2319 /*-----------------------------------------------------------------*/
2321 void unlinkpCode(pCode *pc)
2327 fprintf(stderr,"Unlinking: ");
2328 printpCode(stderr, pc);
2331 pc->prev->next = pc->next;
2333 pc->next->prev = pc->prev;
2335 pc->prev = pc->next = NULL;
2338 static void genericDestruct(pCode *pc)
2340 //fprintf(stderr,"warning, calling default pCode destructor\n");
2349 /*-----------------------------------------------------------------*/
2350 /*-----------------------------------------------------------------*/
2351 void pBlockRegs(FILE *of, pBlock *pb)
2356 r = setFirstItem(pb->tregisters);
2358 r = setNextItem(pb->tregisters);
2363 /*-----------------------------------------------------------------*/
2364 /*-----------------------------------------------------------------*/
2365 char *get_op(pCodeOp *pcop,char *buffer, int size)
2370 int use_buffer = 1; // copy the string to the passed buffer pointer
2375 use_buffer = 0; // Don't bother copying the string to the buffer.
2379 switch(pcop->type) {
2383 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2386 return PCOR(pcop)->r->name;
2389 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2392 SAFE_snprintf(&buffer,&size,"%s",r->name);
2402 if(PCOI(pcop)->_const) {
2404 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2405 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2408 8 * PCOI(pcop)->offset );
2410 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2413 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2414 SAFE_snprintf(&s,&size,"(%s + %d)",
2416 PCOI(pcop)->index );
2418 SAFE_snprintf(&s,&size,"%s",pcop->name);
2425 //size = sizeof(buffer);
2426 if( PCOR(pcop)->instance) {
2427 SAFE_snprintf(&s,&size,"(%s + %d)",
2429 PCOR(pcop)->instance );
2430 //fprintf(stderr,"PO_DIR %s\n",buffer);
2432 SAFE_snprintf(&s,&size,"%s",pcop->name);
2438 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2447 return "NO operand";
2451 /*-----------------------------------------------------------------*/
2452 /*-----------------------------------------------------------------*/
2453 static char *get_op_from_instruction( pCodeInstruction *pcc)
2457 return get_op(pcc->pcop,NULL,0);
2459 return ("ERROR Null: "__FUNCTION__);
2463 /*-----------------------------------------------------------------*/
2464 /*-----------------------------------------------------------------*/
2465 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2468 fprintf(of,"pcodeopprint- not implemented\n");
2471 /*-----------------------------------------------------------------*/
2472 /*-----------------------------------------------------------------*/
2473 char *pCode2str(char *str, int size, pCode *pc)
2481 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2483 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2485 if(PCI(pc)->isBitInst) {
2486 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2487 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2488 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2489 PCI(pc)->pcop->name ,
2490 PCI(pc)->pcop->name );
2492 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2493 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2494 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2495 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2497 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2498 //PCI(pc)->pcop->t.bit );
2501 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2502 if( PCI(pc)->num_ops == 2)
2503 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2505 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2508 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2510 if( PCI(pc)->num_ops == 2)
2511 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2519 /* assuming that comment ends with a \n */
2520 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2524 /* assuming that inline code ends with a \n */
2525 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2529 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2532 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2535 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2538 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2541 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2550 /*-----------------------------------------------------------------*/
2551 /* genericPrint - the contents of a pCode to a file */
2552 /*-----------------------------------------------------------------*/
2553 static void genericPrint(FILE *of, pCode *pc)
2561 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2565 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2569 // If the opcode has a label, print that first
2571 pBranch *pbl = PCI(pc)->label;
2572 while(pbl && pbl->pc) {
2573 if(pbl->pc->type == PC_LABEL)
2574 pCodePrintLabel(of, pbl->pc);
2580 genericPrint(of,PCODE(PCI(pc)->cline));
2585 pCode2str(str, 256, pc);
2587 fprintf(of,"%s",str);
2590 fprintf(of, "\t;key=%03x",pc->seq);
2592 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2596 pBranch *dpb = pc->to; // debug
2598 switch ( dpb->pc->type) {
2600 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2603 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2606 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2609 fprintf(of, "\t;flow");
2623 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2624 if(PCW(pc)->pci.label)
2625 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2627 if(PCW(pc)->operand) {
2628 fprintf(of,";\toperand ");
2629 pCodeOpPrint(of,PCW(pc)->operand );
2634 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2638 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2642 fprintf(of,"unknown pCode type %d\n",pc->type);
2647 /*-----------------------------------------------------------------*/
2648 /* pCodePrintFunction - prints function begin/end */
2649 /*-----------------------------------------------------------------*/
2651 static void pCodePrintFunction(FILE *of, pCode *pc)
2657 if( ((pCodeFunction *)pc)->modname)
2658 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2660 if(PCF(pc)->fname) {
2661 pBranch *exits = PCF(pc)->to;
2663 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2666 exits = exits->next;
2669 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2672 if((PCF(pc)->from &&
2673 PCF(pc)->from->pc->type == PC_FUNCTION &&
2674 PCF(PCF(pc)->from->pc)->fname) )
2675 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2677 fprintf(of,"; exit point [can't find entry point]\n");
2680 /*-----------------------------------------------------------------*/
2681 /* pCodePrintLabel - prints label */
2682 /*-----------------------------------------------------------------*/
2684 static void pCodePrintLabel(FILE *of, pCode *pc)
2691 fprintf(of,"%s\n",PCL(pc)->label);
2692 else if (PCL(pc)->key >=0)
2693 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2695 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2698 /*-----------------------------------------------------------------*/
2699 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2700 /* remove it if it is found. */
2701 /*-----------------------------------------------------------------*/
2702 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2709 if(pcl->type == PC_OPCODE)
2710 b = PCI(pcl)->label;
2712 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2717 //fprintf (stderr, "%s \n",__FUNCTION__);
2718 //pcl->print(stderr,pcl);
2719 //pc->print(stderr,pc);
2722 //fprintf (stderr, "found label\n");
2726 bprev->next = b->next; /* Not first pCode in chain */
2730 PCI(pcl)->label = b->next; /* First pCode in chain */
2733 return; /* A label can't occur more than once */
2741 /*-----------------------------------------------------------------*/
2742 /*-----------------------------------------------------------------*/
2743 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2759 /*-----------------------------------------------------------------*/
2760 /* pBranchLink - given two pcodes, this function will link them */
2761 /* together through their pBranches */
2762 /*-----------------------------------------------------------------*/
2763 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2767 // Declare a new branch object for the 'from' pCode.
2769 //_ALLOC(b,sizeof(pBranch));
2770 b = Safe_calloc(1,sizeof(pBranch));
2771 b->pc = PCODE(t); // The link to the 'to' pCode.
2774 f->to = pBranchAppend(f->to,b);
2776 // Now do the same for the 'to' pCode.
2778 //_ALLOC(b,sizeof(pBranch));
2779 b = Safe_calloc(1,sizeof(pBranch));
2783 t->from = pBranchAppend(t->from,b);
2788 /*-----------------------------------------------------------------*/
2789 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2791 /*-----------------------------------------------------------------*/
2792 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2805 /*-----------------------------------------------------------------*/
2806 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2807 /*-----------------------------------------------------------------*/
2808 static void pCodeUnlink(pCode *pc)
2813 if(!pc->prev || !pc->next) {
2814 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2818 /* first remove the pCode from the chain */
2819 pc->prev->next = pc->next;
2820 pc->next->prev = pc->prev;
2822 /* Now for the hard part... */
2824 /* Remove the branches */
2828 pc1 = pb1->pc; /* Get the pCode that branches to the
2829 * one we're unlinking */
2831 /* search for the link back to this pCode (the one we're
2833 if(pb2 = pBranchFind(pc1->to,pc)) {
2834 pb2->pc = pc->to->pc; // make the replacement
2836 /* if the pCode we're unlinking contains multiple 'to'
2837 * branches (e.g. this a skip instruction) then we need
2838 * to copy these extra branches to the chain. */
2840 pBranchAppend(pb2, pc->to->next);
2849 /*-----------------------------------------------------------------*/
2850 /*-----------------------------------------------------------------*/
2852 static void genericAnalyze(pCode *pc)
2862 // Go through the pCodes that are in pCode chain and link
2863 // them together through the pBranches. Note, the pCodes
2864 // are linked together as a contiguous stream like the
2865 // assembly source code lines. The linking here mimics this
2866 // except that comments are not linked in.
2868 pCode *npc = pc->next;
2870 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2871 pBranchLink(pc,npc);
2876 /* reached the end of the pcode chain without finding
2877 * an instruction we could link to. */
2881 fprintf(stderr,"analyze PC_FLOW\n");
2888 /*-----------------------------------------------------------------*/
2889 /*-----------------------------------------------------------------*/
2890 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2894 if(pc->type == PC_LABEL) {
2895 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2898 if(pc->type == PC_OPCODE) {
2899 pbr = PCI(pc)->label;
2901 if(pbr->pc->type == PC_LABEL) {
2902 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2912 /*-----------------------------------------------------------------*/
2913 /*-----------------------------------------------------------------*/
2914 int checkLabel(pCode *pc)
2918 if(pc && isPCI(pc)) {
2919 pbr = PCI(pc)->label;
2921 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2931 /*-----------------------------------------------------------------*/
2932 /* findLabelinpBlock - Search the pCode for a particular label */
2933 /*-----------------------------------------------------------------*/
2934 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2941 for(pc = pb->pcHead; pc; pc = pc->next)
2942 if(compareLabel(pc,pcop_label))
2948 /*-----------------------------------------------------------------*/
2949 /* findLabel - Search the pCode for a particular label */
2950 /*-----------------------------------------------------------------*/
2951 pCode * findLabel(pCodeOpLabel *pcop_label)
2959 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2960 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2964 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2968 /*-----------------------------------------------------------------*/
2969 /* findNextpCode - given a pCode, find the next of type 'pct' */
2970 /* in the linked list */
2971 /*-----------------------------------------------------------------*/
2972 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2985 /*-----------------------------------------------------------------*/
2986 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2987 /* in the linked list */
2988 /*-----------------------------------------------------------------*/
2989 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3001 /*-----------------------------------------------------------------*/
3002 /* findNextInstruction - given a pCode, find the next instruction */
3003 /* in the linked list */
3004 /*-----------------------------------------------------------------*/
3005 pCode * findNextInstruction(pCode *pci)
3010 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3014 fprintf(stderr,"findNextInstruction: ");
3015 printpCode(stderr, pc);
3020 //fprintf(stderr,"Couldn't find instruction\n");
3024 /*-----------------------------------------------------------------*/
3025 /* findNextInstruction - given a pCode, find the next instruction */
3026 /* in the linked list */
3027 /*-----------------------------------------------------------------*/
3028 pCode * findPrevInstruction(pCode *pci)
3030 return findPrevpCode(pci, PC_OPCODE);
3033 /*-----------------------------------------------------------------*/
3034 /* findFunctionEnd - given a pCode find the end of the function */
3035 /* that contains it */
3036 /*-----------------------------------------------------------------*/
3037 pCode * findFunctionEnd(pCode *pc)
3041 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3047 fprintf(stderr,"Couldn't find function end\n");
3052 /*-----------------------------------------------------------------*/
3053 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3054 /* instruction with which it is associated. */
3055 /*-----------------------------------------------------------------*/
3056 static void AnalyzeLabel(pCode *pc)
3065 static void AnalyzeGOTO(pCode *pc)
3068 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3072 static void AnalyzeSKIP(pCode *pc)
3075 pBranchLink(pc,findNextInstruction(pc->next));
3076 pBranchLink(pc,findNextInstruction(pc->next->next));
3080 static void AnalyzeRETURN(pCode *pc)
3083 // branch_link(pc,findFunctionEnd(pc->next));
3089 /*-----------------------------------------------------------------*/
3090 /*-----------------------------------------------------------------*/
3091 regs * getRegFromInstruction(pCode *pc)
3096 PCI(pc)->num_ops == 0 )
3099 switch(PCI(pc)->pcop->type) {
3102 return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3106 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3107 return PCOR(PCI(pc)->pcop)->r;
3110 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3111 return NULL; // PCOR(PCI(pc)->pcop)->r;
3114 return PCOR(PCI(pc)->pcop)->r;
3117 //fprintf(stderr, "getRegFromInstruction - dir\n");
3118 return PCOR(PCI(pc)->pcop)->r;
3120 //fprintf(stderr, "getRegFromInstruction - literal\n");
3124 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3125 //genericPrint(stderr, pc);
3133 /*-----------------------------------------------------------------*/
3134 /*-----------------------------------------------------------------*/
3136 void AnalyzepBlock(pBlock *pb)
3143 /* Find all of the registers used in this pBlock
3144 * by looking at each instruction and examining it's
3147 for(pc = pb->pcHead; pc; pc = pc->next) {
3149 /* Is this an instruction with operands? */
3150 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3152 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3154 /* Loop through all of the registers declared so far in
3155 this block and see if we find this one there */
3157 regs *r = setFirstItem(pb->tregisters);
3160 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3161 PCOR(PCI(pc)->pcop)->r = r;
3164 r = setNextItem(pb->tregisters);
3168 /* register wasn't found */
3169 //r = Safe_calloc(1, sizeof(regs));
3170 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3171 //addSet(&pb->tregisters, r);
3172 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3173 //PCOR(PCI(pc)->pcop)->r = r;
3174 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3176 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3179 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3180 if(PCOR(PCI(pc)->pcop)->r) {
3181 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3182 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3184 if(PCI(pc)->pcop->name)
3185 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3187 fprintf(stderr,"ERROR: NULL register\n");
3196 /*-----------------------------------------------------------------*/
3198 /*-----------------------------------------------------------------*/
3199 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3201 void InsertpFlow(pCode *pc, pCode **pflow)
3203 PCFL(*pflow)->end = pc;
3205 if(!pc || !pc->next)
3208 *pflow = newpCodeFlow();
3209 pCodeInsertAfter(pc, *pflow);
3212 /*-----------------------------------------------------------------*/
3213 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3214 /* the flow blocks. */
3216 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3217 * point the instruction flow changes.
3219 /*-----------------------------------------------------------------*/
3220 void BuildFlow(pBlock *pb)
3223 pCode *last_pci=NULL;
3230 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3231 /* Insert a pCodeFlow object at the beginning of a pBlock */
3233 pflow = newpCodeFlow(); /* Create a new Flow object */
3234 pflow->next = pb->pcHead; /* Make the current head the next object */
3235 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3236 pb->pcHead = pflow; /* Make the Flow object the head */
3239 for( pc = findNextInstruction(pb->pcHead);
3241 pc=findNextInstruction(pc)) {
3244 PCI(pc)->pcflow = PCFL(pflow);
3246 //fprintf(stderr," build: ");
3247 //pflow->print(stderr,pflow);
3249 if( PCI(pc)->isSkip) {
3251 /* The two instructions immediately following this one
3252 * mark the beginning of a new flow segment */
3254 while(pc && PCI(pc)->isSkip) {
3256 PCI(pc)->pcflow = PCFL(pflow);
3260 InsertpFlow(pc, &pflow);
3261 pc=findNextInstruction(pc->next);
3269 PCI(pc)->pcflow = PCFL(pflow);
3271 InsertpFlow(pc, &pflow);
3273 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3275 InsertpFlow(pc, &pflow);
3278 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3280 /* This instruction marks the beginning of a
3281 * new flow segment */
3285 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3287 PCI(pc)->pcflow = PCFL(pflow);
3294 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3295 PCFL(pflow)->end = pb->pcTail;
3298 /*-------------------------------------------------------------------*/
3299 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3300 /* the flow blocks. */
3302 * unBuildFlow removes pCodeFlow objects from a pCode chain
3304 /*-----------------------------------------------------------------*/
3305 void unBuildFlow(pBlock *pb)
3314 pCode *pcn = pc->next;
3318 PCI(pc)->pcflow = NULL;
3320 } else if(isPCFL(pc)) {
3330 /*-----------------------------------------------------------------*/
3331 /*-----------------------------------------------------------------*/
3332 void dumpCond(int cond)
3335 static char *pcc_str[] = {
3349 int ncond = sizeof(pcc_str) / sizeof(char *);
3352 fprintf(stderr, "0x%04X\n",cond);
3354 for(i=0,j=1; i<ncond; i++, j<<=1)
3356 fprintf(stderr, " %s\n",pcc_str[i]);
3360 /*-----------------------------------------------------------------*/
3361 /*-----------------------------------------------------------------*/
3362 void FlowStats(pCodeFlow *pcflow)
3370 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3372 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3375 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3380 fprintf(stderr, " FlowStats inCond: ");
3381 dumpCond(pcflow->inCond);
3382 fprintf(stderr, " FlowStats outCond: ");
3383 dumpCond(pcflow->outCond);
3387 /*-----------------------------------------------------------------*
3388 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3389 * if it affects the banking bits.
3391 * return: -1 == Banking bits are unaffected by this pCode.
3393 * return: > 0 == Banking bits are affected.
3395 * If the banking bits are affected, then the returned value describes
3396 * which bits are affected and how they're affected. The lower half
3397 * of the integer maps to the bits that are affected, the upper half
3398 * to whether they're set or cleared.
3400 *-----------------------------------------------------------------*/
3401 #define SET_BANK_BIT (1 << 16)
3402 #define CLR_BANK_BIT 0
3404 int isBankInstruction(pCode *pc)
3412 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3414 /* Check to see if the register banks are changing */
3415 if(PCI(pc)->isModReg) {
3417 pCodeOp *pcop = PCI(pc)->pcop;
3418 switch(PCI(pc)->op) {
3421 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3422 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3423 return SET_BANK_BIT | PIC_RP0_BIT;
3426 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3427 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3428 return CLR_BANK_BIT | PIC_RP0_BIT;
3433 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3434 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3435 return CLR_BANK_BIT | PIC_RP1_BIT;
3437 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3438 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3439 return CLR_BANK_BIT | PIC_RP1_BIT;
3443 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3444 //genericPrint(stderr, pc);
3455 /*-----------------------------------------------------------------*/
3456 /*-----------------------------------------------------------------*/
3457 void FillFlow(pCodeFlow *pcflow)
3466 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3468 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3471 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3478 isBankInstruction(pc);
3480 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3484 fprintf(stderr, " FillFlow - Bad end of flow\n");
3486 fprintf(stderr, " FillFlow - Ending flow with\n ");
3487 pc->print(stderr,pc);
3490 fprintf(stderr, " FillFlow inCond: ");
3491 dumpCond(pcflow->inCond);
3492 fprintf(stderr, " FillFlow outCond: ");
3493 dumpCond(pcflow->outCond);
3497 /*-----------------------------------------------------------------*/
3498 /*-----------------------------------------------------------------*/
3499 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3501 pCodeFlowLink *fromLink, *toLink;
3503 if(!from || !to || !to->pcflow || !from->pcflow)
3506 fromLink = newpCodeFlowLink(from->pcflow);
3507 toLink = newpCodeFlowLink(to->pcflow);
3509 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3510 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3514 /*-----------------------------------------------------------------*/
3515 /*-----------------------------------------------------------------*/
3516 void LinkFlow(pBlock *pb)
3522 //fprintf(stderr,"linkflow \n");
3524 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3526 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3529 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3531 //fprintf(stderr," link: ");
3532 //pcflow->print(stderr,pcflow);
3534 //FillFlow(PCFL(pcflow));
3536 pc = PCFL(pcflow)->end;
3538 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3539 if(isPCI_SKIP(pc)) {
3540 //fprintf(stderr, "ends with skip\n");
3541 //pc->print(stderr,pc);
3542 pct=findNextInstruction(pc->next);
3543 LinkFlow_pCode(PCI(pc),PCI(pct));
3544 pct=findNextInstruction(pct->next);
3545 LinkFlow_pCode(PCI(pc),PCI(pct));
3549 if(isPCI_BRANCH(pc)) {
3550 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3552 //fprintf(stderr, "ends with branch\n ");
3553 //pc->print(stderr,pc);
3555 if(!(pcol && isPCOLAB(pcol))) {
3556 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3557 pc->print(stderr,pc);
3558 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3563 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3564 LinkFlow_pCode(PCI(pc),PCI(pct));
3566 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3572 //fprintf(stderr, "ends with non-branching instruction:\n");
3573 //pc->print(stderr,pc);
3575 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3581 //fprintf(stderr, "ends with unknown\n");
3582 //pc->print(stderr,pc);
3586 //fprintf(stderr, "ends with nothing: ERROR\n");
3591 /*-----------------------------------------------------------------*/
3592 /*-----------------------------------------------------------------*/
3593 int isPCinFlow(pCode *pc, pCode *pcflow)
3599 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3602 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3608 /*-----------------------------------------------------------------*/
3609 /*-----------------------------------------------------------------*/
3610 void BanksUsedFlow2(pCode *pcflow)
3619 if(!isPCFL(pcflow)) {
3620 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3624 pc = findNextInstruction(pcflow->next);
3626 PCFL(pcflow)->lastBank = -1;
3628 while(isPCinFlow(pc,pcflow)) {
3630 int bank_selected = isBankInstruction(pc);
3632 //if(PCI(pc)->pcflow)
3633 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3635 if(bank_selected > 0) {
3636 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3638 /* This instruction is modifying banking bits before accessing registers */
3640 PCFL(pcflow)->firstBank = -1;
3642 if(PCFL(pcflow)->lastBank == -1)
3643 PCFL(pcflow)->lastBank = 0;
3645 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3646 if(bank_selected & SET_BANK_BIT)
3647 PCFL(pcflow)->lastBank |= bank;
3651 reg = getRegFromInstruction(pc);
3653 if(reg && !isREGinBank(reg, bank)) {
3654 int allbanks = REGallBanks(reg);
3656 PCFL(pcflow)->firstBank = allbanks;
3658 PCFL(pcflow)->lastBank = allbanks;
3665 pc = findNextInstruction(pc->next);
3668 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3669 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3674 /*-----------------------------------------------------------------*/
3675 /*-----------------------------------------------------------------*/
3676 void BanksUsedFlow(pBlock *pb)
3681 //pb->pcHead->print(stderr, pb->pcHead);
3683 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3684 //pcflow->print(stderr,pcflow);
3686 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3688 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3690 BanksUsedFlow2(pcflow);
3696 /*-----------------------------------------------------------------*/
3697 /*-----------------------------------------------------------------*/
3698 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3706 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3708 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3709 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3711 pCodeInsertAfter(pc->prev, new_pc);
3713 /* Move the label, if there is one */
3715 if(PCI(pc)->label) {
3716 PCI(new_pc)->label = PCI(pc)->label;
3717 PCI(pc)->label = NULL;
3720 /* The new instruction has the same pcflow block */
3721 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3724 /*-----------------------------------------------------------------*/
3725 /*-----------------------------------------------------------------*/
3726 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3737 pc = findNextInstruction(pcfl->pc.next);
3739 while(isPCinFlow(pc,PCODE(pcfl))) {
3742 reg = getRegFromInstruction(pc);
3745 fprintf(stderr, " %s ",reg->name);
3746 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3751 if(reg && REG_BANK(reg)!=cur_bank) {
3752 /* Examine the instruction before this one to make sure it is
3753 * not a skip type instruction */
3754 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3755 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3756 int b = cur_bank ^ REG_BANK(reg);
3758 //fprintf(stderr, "Cool! can switch banks\n");
3759 cur_bank = REG_BANK(reg);
3764 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3767 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3768 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3772 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3773 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3775 insertBankSwitch(pc, -1, -1);
3778 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3779 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3780 pCodeInsertAfter(pc->prev, new_pc);
3781 if(PCI(pc)->label) {
3782 PCI(new_pc)->label = PCI(pc)->label;
3783 PCI(pc)->label = NULL;
3787 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3788 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3789 pCodeInsertAfter(pc, new_pc);
3795 //fprintf(stderr, "Bummer can't switch banks\n");
3801 pc = findNextInstruction(pc->next);
3805 if(pcprev && cur_bank) {
3806 /* Brute force - make sure that we point to bank 0 at the
3807 * end of each flow block */
3808 new_pc = newpCode(POC_BCF,
3809 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3810 pCodeInsertAfter(pcprev, new_pc);
3816 /*-----------------------------------------------------------------*/
3817 /*int compareBankFlow - compare the banking requirements between */
3819 /*-----------------------------------------------------------------*/
3820 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3823 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3826 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3829 if(pcflow->firstBank == -1)
3833 if(pcflowLink->pcflow->firstBank == -1) {
3834 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3835 pcflowLink->pcflow->to :
3836 pcflowLink->pcflow->from);
3837 return compareBankFlow(pcflow, pctl, toORfrom);
3841 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3844 pcflowLink->bank_conflict++;
3845 pcflowLink->pcflow->FromConflicts++;
3846 pcflow->ToConflicts++;
3849 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3852 pcflowLink->bank_conflict++;
3853 pcflowLink->pcflow->ToConflicts++;
3854 pcflow->FromConflicts++;
3858 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3859 pcflowLink->pcflow->pc.seq,
3860 pcflowLink->pcflow->FromConflicts,
3861 pcflowLink->pcflow->ToConflicts);
3866 /*-----------------------------------------------------------------*/
3867 /*-----------------------------------------------------------------*/
3868 void FixBankFlow(pBlock *pb)
3872 pCodeFlowLink *pcfl;
3874 pCode *pcflow_max_To=NULL;
3875 pCode *pcflow_max_From=NULL;
3876 int max_ToConflicts=0;
3877 int max_FromConflicts=0;
3879 //fprintf(stderr,"Fix Bank flow \n");
3880 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3884 First loop through all of the flow objects in this pcode block
3885 and fix the ones that have banking conflicts between the
3889 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3891 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3893 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3895 if(!isPCFL(pcflow)) {
3896 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3900 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3901 PCFL(pcflow)->firstBank >= 0 &&
3902 PCFL(pcflow)->lastBank >= 0 ) {
3904 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3905 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3907 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3908 BanksUsedFlow2(pcflow);
3913 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3915 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3917 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3922 if(!isPCFL(pcflow)) {
3923 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3927 PCFL(pcflow)->FromConflicts = 0;
3928 PCFL(pcflow)->ToConflicts = 0;
3933 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3934 pcfl = setFirstItem(PCFL(pcflow)->from);
3937 pc = PCODE(pcfl->pcflow);
3940 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3941 pc->print(stderr,pc);
3944 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3947 pcfl=setNextItem(PCFL(pcflow)->from);
3950 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3951 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3953 FixRegisterBankingInFlow(PCFL(pcflow),0);
3954 BanksUsedFlow2(pcflow);
3956 continue; /* Don't need to check the flow from here - it's already been fixed */
3963 pcfl = setFirstItem(PCFL(pcflow)->to);
3966 pc = PCODE(pcfl->pcflow);
3968 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3969 pc->print(stderr,pc);
3972 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
3975 pcfl=setNextItem(PCFL(pcflow)->to);
3978 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
3979 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3981 FixRegisterBankingInFlow(PCFL(pcflow),0);
3982 BanksUsedFlow2(pcflow);
3987 Loop through the flow objects again and find the ones with the
3991 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3993 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3995 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
3996 pcflow_max_To = pcflow;
3998 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
3999 pcflow_max_From = pcflow;
4003 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4004 PCFL(pcflow_max_To)->pc.seq,
4005 PCFL(pcflow_max_To)->ToConflicts);
4008 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4009 PCFL(pcflow_max_From)->pc.seq,
4010 PCFL(pcflow_max_From)->FromConflicts);
4014 /*-----------------------------------------------------------------*/
4015 /*-----------------------------------------------------------------*/
4016 void DumpFlow(pBlock *pb)
4020 pCodeFlowLink *pcfl;
4023 fprintf(stderr,"Dump flow \n");
4024 pb->pcHead->print(stderr, pb->pcHead);
4026 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4027 pcflow->print(stderr,pcflow);
4029 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4031 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4033 if(!isPCFL(pcflow)) {
4034 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4037 fprintf(stderr,"dumping: ");
4038 pcflow->print(stderr,pcflow);
4039 FlowStats(PCFL(pcflow));
4041 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4043 pc = PCODE(pcfl->pcflow);
4045 fprintf(stderr, " from seq %d:\n",pc->seq);
4047 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4048 pc->print(stderr,pc);
4053 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4055 pc = PCODE(pcfl->pcflow);
4057 fprintf(stderr, " to seq %d:\n",pc->seq);
4059 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4060 pc->print(stderr,pc);
4069 /*-----------------------------------------------------------------*/
4070 /*-----------------------------------------------------------------*/
4071 int OptimizepBlock(pBlock *pb)
4076 if(!pb || !peepOptimizing)
4079 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4081 for(pc = pb->pcHead; pc; pc = pc->next)
4082 matches += pCodePeepMatchRule(pc);
4085 pc = findNextInstruction(pb->pcHead);
4090 if(pCodePeepMatchRule(pc)) {
4095 pc = findNextInstruction(pcprev->next);
4097 pc = findNextInstruction(pb->pcHead);
4099 pc = findNextInstruction(pc->next);
4103 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4108 /*-----------------------------------------------------------------*/
4109 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4110 /*-----------------------------------------------------------------*/
4111 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4115 for(pc = pcs; pc; pc = pc->next) {
4117 if((pc->type == PC_OPCODE) &&
4119 (PCI(pc)->pcop->type == PO_LABEL) &&
4120 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4128 /*-----------------------------------------------------------------*/
4129 /*-----------------------------------------------------------------*/
4130 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4135 (PCI(pc)->pcop->type == PO_LABEL)) {
4137 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4139 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4141 free(pcol->pcop.name);
4143 sprintf(buffer,"_%05d_DS_",pcl->key);
4145 pcol->pcop.name = Safe_strdup(buffer);
4146 pcol->key = pcl->key;
4147 //pc->print(stderr,pc);
4154 /*-----------------------------------------------------------------*/
4155 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4156 /* pCode chain if they're not used. */
4157 /*-----------------------------------------------------------------*/
4158 void pBlockRemoveUnusedLabels(pBlock *pb)
4160 pCode *pc; pCodeLabel *pcl;
4165 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4167 pBranch *pbr = PCI(pc)->label;
4168 if(pbr && pbr->next) {
4169 pCode *pcd = pb->pcHead;
4171 //fprintf(stderr, "multiple labels\n");
4172 //pc->print(stderr,pc);
4177 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4178 //fprintf(stderr,"Used by:\n");
4179 //pcd->print(stderr,pcd);
4181 exchangeLabels(PCL(pbr->pc),pcd);
4190 for(pc = pb->pcHead; pc; pc = pc->next) {
4192 if(isPCL(pc)) // pc->type == PC_LABEL)
4194 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4195 pcl = PCL(PCI(pc)->label->pc);
4198 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4200 /* This pCode is a label, so search the pBlock to see if anyone
4203 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4204 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4205 /* Couldn't find an instruction that refers to this label
4206 * So, unlink the pCode label from it's pCode chain
4207 * and destroy the label */
4208 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4210 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4211 if(pc->type == PC_LABEL) {
4213 pCodeLabelDestruct(pc);
4215 unlinkpCodeFromBranch(pc, PCODE(pcl));
4216 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4227 /*-----------------------------------------------------------------*/
4228 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4229 /* chain and put them into pBranches that are */
4230 /* associated with the appropriate pCode */
4232 /*-----------------------------------------------------------------*/
4233 void pBlockMergeLabels(pBlock *pb)
4236 pCode *pc, *pcnext=NULL;
4241 /* First, Try to remove any unused labels */
4242 //pBlockRemoveUnusedLabels(pb);
4244 /* Now loop through the pBlock and merge the labels with the opcodes */
4246 for(pc = pb->pcHead; pc; pc = pc->next) {
4248 if(pc->type == PC_LABEL) {
4250 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4251 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4252 if((pcnext = findNextInstruction(pc) )) {
4254 pCode *pcn = pc->next;
4256 // Unlink the pCode label from it's pCode chain
4259 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4260 // And link it into the instruction's pBranch labels. (Note, since
4261 // it's possible to have multiple labels associated with one instruction
4262 // we must provide a means to accomodate the additional labels. Thus
4263 // the labels are placed into the singly-linked list "label" as
4264 // opposed to being a single member of the pCodeInstruction.)
4266 //_ALLOC(pbr,sizeof(pBranch));
4267 pbr = Safe_calloc(1,sizeof(pBranch));
4272 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4277 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4279 } else if(pc->type == PC_CSOURCE) {
4281 /* merge the source line symbolic info into the next instruction */
4282 if((pcnext = findNextInstruction(pc) )) {
4284 pCode *pcn = pc->next;
4286 // Unlink the pCode label from it's pCode chain
4288 PCI(pcnext)->cline = PCCS(pc);
4289 //fprintf(stderr, "merging CSRC\n");
4290 //genericPrint(stderr,pcnext);
4297 pBlockRemoveUnusedLabels(pb);
4301 /*-----------------------------------------------------------------*/
4302 /*-----------------------------------------------------------------*/
4303 int OptimizepCode(char dbName)
4305 #define MAX_PASSES 4
4314 DFPRINTF((stderr," Optimizing pCode\n"));
4318 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4319 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4320 matches += OptimizepBlock(pb);
4323 while(matches && ++passes < MAX_PASSES);
4328 /*-----------------------------------------------------------------*/
4329 /* popCopyGPR2Bit - copy a pcode operator */
4330 /*-----------------------------------------------------------------*/
4332 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4336 pcop = newpCodeOpBit(pc->name, bitval, 0);
4338 if( !( (pcop->type == PO_LABEL) ||
4339 (pcop->type == PO_LITERAL) ||
4340 (pcop->type == PO_STR) ))
4341 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4349 /*-----------------------------------------------------------------*/
4350 /*-----------------------------------------------------------------*/
4351 int InstructionRegBank(pCode *pc)
4355 if( (reg = getRegFromInstruction(pc)) == NULL)
4358 return REG_BANK(reg);
4363 /*-----------------------------------------------------------------*/
4364 /*-----------------------------------------------------------------*/
4365 void FixRegisterBanking(pBlock *pb)
4377 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4378 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4381 /* loop through all of the flow blocks with in one pblock */
4383 //fprintf(stderr,"Register banking\n");
4386 /* at this point, pc should point to a PC_FLOW object */
4389 /* for each flow block, determine the register banking
4394 //genericPrint(stderr, pc);
4396 reg = getRegFromInstruction(pc);
4399 fprintf(stderr, " %s ",reg->name);
4400 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4404 if(reg && REG_BANK(reg)!=cur_bank) {
4405 /* Examine the instruction before this one to make sure it is
4406 * not a skip type instruction */
4407 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4408 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4409 int b = cur_bank ^ REG_BANK(reg);
4411 //fprintf(stderr, "Cool! can switch banks\n");
4412 cur_bank = REG_BANK(reg);
4414 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4415 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4416 pCodeInsertAfter(pc->prev, new_pc);
4417 if(PCI(pc)->label) {
4418 PCI(new_pc)->label = PCI(pc)->label;
4419 PCI(pc)->label = NULL;
4422 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4423 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4424 pCodeInsertAfter(pc, new_pc);
4430 //fprintf(stderr, "Bummer can't switch banks\n");
4438 // } while(pc && !(isPCFL(pc)));
4443 if(pcprev && cur_bank) {
4444 /* Brute force - make sure that we point to bank 0 at the
4445 * end of each flow block */
4446 new_pc = newpCode(POC_BCF,
4447 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4448 pCodeInsertAfter(pcprev, new_pc);
4454 void pBlockDestruct(pBlock *pb)
4465 /*-----------------------------------------------------------------*/
4466 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4467 /* name dbName and combine them */
4468 /* into one block */
4469 /*-----------------------------------------------------------------*/
4470 void mergepBlocks(char dbName)
4473 pBlock *pb, *pbmerged = NULL,*pbn;
4475 pb = the_pFile->pbHead;
4477 //fprintf(stderr," merging blocks named %c\n",dbName);
4481 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4482 if( getpBlock_dbName(pb) == dbName) {
4484 //fprintf(stderr," merged block %c\n",dbName);
4489 addpCode2pBlock(pbmerged, pb->pcHead);
4490 /* addpCode2pBlock doesn't handle the tail: */
4491 pbmerged->pcTail = pb->pcTail;
4493 pb->prev->next = pbn;
4495 pbn->prev = pb->prev;
4500 //printpBlock(stderr, pbmerged);
4507 /*-----------------------------------------------------------------*/
4508 /* AnalyzeBanking - Called after the memory addresses have been */
4509 /* assigned to the registers. */
4511 /*-----------------------------------------------------------------*/
4512 void AnalyzeBanking(void)
4521 /* Phase 2 - Flow Analysis - Register Banking
4523 * In this phase, the individual flow blocks are examined
4524 * and register banking is fixed.
4527 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4528 //FixRegisterBanking(pb);
4530 /* Phase 2 - Flow Analysis
4532 * In this phase, the pCode is partition into pCodeFlow
4533 * blocks. The flow blocks mark the points where a continuous
4534 * stream of instructions changes flow (e.g. because of
4535 * a call or goto or whatever).
4538 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4542 /* Phase 2 - Flow Analysis - linking flow blocks
4544 * In this phase, the individual flow blocks are examined
4545 * to determine their order of excution.
4548 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4552 /* Phase x - Flow Analysis - Used Banks
4554 * In this phase, the individual flow blocks are examined
4555 * to determine the Register Banks they use
4558 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4561 /* Phase x - Flow Analysis - Used Banks
4563 * In this phase, the individual flow blocks are examined
4564 * to determine the Register Banks they use
4567 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4571 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4572 pCodeRegMapLiveRanges(pb);
4574 RemoveUnusedRegisters();
4577 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4581 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4583 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4584 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4585 pcflow = pcflow->next) {
4587 FillFlow(PCFL(pcflow));
4591 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4593 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4594 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4595 pcflow = pcflow->next) {
4597 FlowStats(PCFL(pcflow));
4603 /*-----------------------------------------------------------------*/
4604 /* buildCallTree - look at the flow and extract all of the calls */
4606 /*-----------------------------------------------------------------*/
4607 set *register_usage(pBlock *pb);
4609 void buildCallTree(void )
4620 /* Now build the call tree.
4621 First we examine all of the pCodes for functions.
4622 Keep in mind that the function boundaries coincide
4623 with pBlock boundaries.
4625 The algorithm goes something like this:
4626 We have two nested loops. The outer loop iterates
4627 through all of the pBlocks/functions. The inner
4628 loop iterates through all of the pCodes for
4629 a given pBlock. When we begin iterating through
4630 a pBlock, the variable pc_fstart, pCode of the start
4631 of a function, is cleared. We then search for pCodes
4632 of type PC_FUNCTION. When one is encountered, we
4633 initialize pc_fstart to this and at the same time
4634 associate a new pBranch object that signifies a
4635 branch entry. If a return is found, then this signifies
4636 a function exit point. We'll link the pCodes of these
4637 returns to the matching pc_fstart.
4639 When we're done, a doubly linked list of pBranches
4640 will exist. The head of this list is stored in
4641 `the_pFile', which is the meta structure for all
4642 of the pCode. Look at the printCallTree function
4643 on how the pBranches are linked together.
4646 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4647 pCode *pc_fstart=NULL;
4648 for(pc = pb->pcHead; pc; pc = pc->next) {
4650 if (PCF(pc)->fname) {
4652 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4653 //fprintf(stderr," found main \n");
4654 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4658 pbr = Safe_calloc(1,sizeof(pBranch));
4659 pbr->pc = pc_fstart = pc;
4662 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4664 // Here's a better way of doing the same:
4665 addSet(&pb->function_entries, pc);
4668 // Found an exit point in a function, e.g. return
4669 // (Note, there may be more than one return per function)
4671 pBranchLink(PCF(pc_fstart), PCF(pc));
4673 addSet(&pb->function_exits, pc);
4675 } else if(isCALL(pc)) {
4676 addSet(&pb->function_calls,pc);
4681 /* Re-allocate the registers so that there are no collisions
4682 * between local variables when one function call another */
4685 // pic14_deallocateAllRegs();
4687 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4694 /*-----------------------------------------------------------------*/
4695 /* AnalyzepCode - parse the pCode that has been generated and form */
4696 /* all of the logical connections. */
4698 /* Essentially what's done here is that the pCode flow is */
4700 /*-----------------------------------------------------------------*/
4702 void AnalyzepCode(char dbName)
4713 /* Phase 1 - Register allocation and peep hole optimization
4715 * The first part of the analysis is to determine the registers
4716 * that are used in the pCode. Once that is done, the peep rules
4717 * are applied to the code. We continue to loop until no more
4718 * peep rule optimizations are found (or until we exceed the
4719 * MAX_PASSES threshold).
4721 * When done, the required registers will be determined.
4727 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4728 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4730 /* First, merge the labels with the instructions */
4731 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4732 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4734 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4735 //fprintf(stderr," analyze and merging block %c\n",dbName);
4736 pBlockMergeLabels(pb);
4739 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4743 changes = OptimizepCode(dbName);
4745 } while(changes && (i++ < MAX_PASSES));
4750 /*-----------------------------------------------------------------*/
4751 /* ispCodeFunction - returns true if *pc is the pCode of a */
4753 /*-----------------------------------------------------------------*/
4754 bool ispCodeFunction(pCode *pc)
4757 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4763 /*-----------------------------------------------------------------*/
4764 /* findFunction - Search for a function by name (given the name) */
4765 /* in the set of all functions that are in a pBlock */
4766 /* (note - I expect this to change because I'm planning to limit */
4767 /* pBlock's to just one function declaration */
4768 /*-----------------------------------------------------------------*/
4769 pCode *findFunction(char *fname)
4776 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4778 pc = setFirstItem(pb->function_entries);
4781 if((pc->type == PC_FUNCTION) &&
4783 (strcmp(fname, PCF(pc)->fname)==0))
4786 pc = setNextItem(pb->function_entries);
4794 void MarkUsedRegisters(set *regset)
4799 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4800 r2 = pic14_regWithIdx(r1->rIdx);
4806 void pBlockStats(FILE *of, pBlock *pb)
4812 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4814 // for now just print the first element of each set
4815 pc = setFirstItem(pb->function_entries);
4817 fprintf(of,";entry: ");
4820 pc = setFirstItem(pb->function_exits);
4822 fprintf(of,";has an exit\n");
4826 pc = setFirstItem(pb->function_calls);
4828 fprintf(of,";functions called:\n");
4831 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4832 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4834 pc = setNextItem(pb->function_calls);
4838 r = setFirstItem(pb->tregisters);
4840 int n = elementsInSet(pb->tregisters);
4842 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4845 fprintf(of,"; %s\n",r->name);
4846 r = setNextItem(pb->tregisters);
4851 /*-----------------------------------------------------------------*/
4852 /*-----------------------------------------------------------------*/
4854 static void sequencepCode(void)
4860 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4862 pb->seq = GpCodeSequenceNumber+1;
4864 for( pc = pb->pcHead; pc; pc = pc->next)
4865 pc->seq = ++GpCodeSequenceNumber;
4871 /*-----------------------------------------------------------------*/
4872 /*-----------------------------------------------------------------*/
4873 set *register_usage(pBlock *pb)
4876 set *registers=NULL;
4877 set *registersInCallPath = NULL;
4879 /* check recursion */
4881 pc = setFirstItem(pb->function_entries);
4888 if(pc->type != PC_FUNCTION)
4889 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4891 pc = setFirstItem(pb->function_calls);
4892 for( ; pc; pc = setNextItem(pb->function_calls)) {
4894 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4895 char *dest = get_op_from_instruction(PCI(pc));
4897 pcn = findFunction(dest);
4899 registersInCallPath = register_usage(pcn->pb);
4901 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4906 pBlockStats(stderr,pb); // debug
4909 // Mark the registers in this block as used.
4911 MarkUsedRegisters(pb->tregisters);
4912 if(registersInCallPath) {
4913 /* registers were used in the functions this pBlock has called */
4914 /* so now, we need to see if these collide with the ones we are */
4917 regs *r1,*r2, *newreg;
4919 DFPRINTF((stderr,"comparing registers\n"));
4921 r1 = setFirstItem(registersInCallPath);
4924 r2 = setFirstItem(pb->tregisters);
4926 while(r2 && (r1->type != REG_STK)) {
4928 if(r2->rIdx == r1->rIdx) {
4929 newreg = pic14_findFreeReg(REG_GPR);
4933 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4937 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4938 r1->rIdx, newreg->rIdx));
4939 r2->rIdx = newreg->rIdx;
4940 //if(r2->name) free(r2->name);
4942 r2->name = Safe_strdup(newreg->name);
4946 newreg->wasUsed = 1;
4948 r2 = setNextItem(pb->tregisters);
4951 r1 = setNextItem(registersInCallPath);
4954 /* Collisions have been resolved. Now free the registers in the call path */
4955 r1 = setFirstItem(registersInCallPath);
4957 if(r1->type != REG_STK) {
4958 newreg = pic14_regWithIdx(r1->rIdx);
4961 r1 = setNextItem(registersInCallPath);
4965 // MarkUsedRegisters(pb->registers);
4967 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4970 DFPRINTF((stderr,"returning regs\n"));
4972 DFPRINTF((stderr,"not returning regs\n"));
4974 DFPRINTF((stderr,"pBlock after register optim.\n"));
4975 pBlockStats(stderr,pb); // debug
4981 /*-----------------------------------------------------------------*/
4982 /* printCallTree - writes the call tree to a file */
4984 /*-----------------------------------------------------------------*/
4985 void pct2(FILE *of,pBlock *pb,int indent)
4989 // set *registersInCallPath = NULL;
4995 return; //recursion ?
4997 pc = setFirstItem(pb->function_entries);
5004 for(i=0;i<indent;i++) // Indentation
5007 if(pc->type == PC_FUNCTION)
5008 fprintf(of,"%s\n",PCF(pc)->fname);
5013 pc = setFirstItem(pb->function_calls);
5014 for( ; pc; pc = setNextItem(pb->function_calls)) {
5016 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5017 char *dest = get_op_from_instruction(PCI(pc));
5019 pcn = findFunction(dest);
5021 pct2(of,pcn->pb,indent+1);
5023 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5031 /*-----------------------------------------------------------------*/
5032 /* printCallTree - writes the call tree to a file */
5034 /*-----------------------------------------------------------------*/
5036 void printCallTree(FILE *of)
5048 fprintf(of, "\npBlock statistics\n");
5049 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5054 fprintf(of,"Call Tree\n");
5055 pbr = the_pFile->functions;
5059 if(!ispCodeFunction(pc))
5060 fprintf(of,"bug in call tree");
5063 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5065 while(pc->next && !ispCodeFunction(pc->next)) {
5067 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5068 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5076 fprintf(of,"\n**************\n\na better call tree\n");
5077 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5082 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5083 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5089 /*-----------------------------------------------------------------*/
5091 /*-----------------------------------------------------------------*/
5093 void InlineFunction(pBlock *pb)
5101 pc = setFirstItem(pb->function_calls);
5103 for( ; pc; pc = setNextItem(pb->function_calls)) {
5106 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5112 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5114 //fprintf(stderr,"Cool can inline:\n");
5115 //pcn->print(stderr,pcn);
5117 //fprintf(stderr,"recursive call Inline\n");
5118 InlineFunction(pcn->pb);
5119 //fprintf(stderr,"return from recursive call Inline\n");
5122 At this point, *pc points to a CALL mnemonic, and
5123 *pcn points to the function that is being called.
5125 To in-line this call, we need to remove the CALL
5126 and RETURN(s), and link the function pCode in with
5132 /* Remove the CALL */
5136 /* remove callee pBlock from the pBlock linked list */
5137 removepBlock(pcn->pb);
5145 /* Remove the Function pCode */
5146 pct = findNextInstruction(pcn->next);
5148 /* Link the function with the callee */
5149 pc->next = pcn->next;
5150 pcn->next->prev = pc;
5152 /* Convert the function name into a label */
5154 pbr = Safe_calloc(1,sizeof(pBranch));
5155 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5157 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5158 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5160 /* turn all of the return's except the last into goto's */
5161 /* check case for 2 instruction pBlocks */
5162 pce = findNextInstruction(pcn->next);
5164 pCode *pce_next = findNextInstruction(pce->next);
5166 if(pce_next == NULL) {
5167 /* found the last return */
5168 pCode *pc_call_next = findNextInstruction(pc_call->next);
5170 //fprintf(stderr,"found last return\n");
5171 //pce->print(stderr,pce);
5172 pce->prev->next = pc_call->next;
5173 pc_call->next->prev = pce->prev;
5174 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5184 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5190 /*-----------------------------------------------------------------*/
5192 /*-----------------------------------------------------------------*/
5194 void InlinepCode(void)
5203 if(!functionInlining)
5206 /* Loop through all of the function definitions and count the
5207 * number of times each one is called */
5208 //fprintf(stderr,"inlining %d\n",__LINE__);
5210 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5212 pc = setFirstItem(pb->function_calls);
5214 for( ; pc; pc = setNextItem(pb->function_calls)) {
5217 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5218 if(pcn && isPCF(pcn)) {
5219 PCF(pcn)->ncalled++;
5222 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5227 //fprintf(stderr,"inlining %d\n",__LINE__);
5229 /* Now, Loop through the function definitions again, but this
5230 * time inline those functions that have only been called once. */
5232 InlineFunction(the_pFile->pbHead);
5233 //fprintf(stderr,"inlining %d\n",__LINE__);
5235 for(pb = the_pFile->pbHead; pb; pb = pb->next)