1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 /****************************************************************/
39 /****************************************************************/
41 peepCommand peepCommands[] = {
43 {NOTBITSKIP, "_NOTBITSKIP_"},
44 {BITSKIP, "_BITSKIP_"},
45 {INVERTBITSKIP, "_INVERTBITSKIP_"},
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
64 static int mnemonics_initialized = 0;
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
72 static pFile *the_pFile = NULL;
73 static pBlock *pb_dead_pcodes = NULL;
75 /* Hardcoded flags to change the behavior of the PIC port */
76 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
77 static int functionInlining = 1; /* inline functions if nonzero */
79 static int GpCodeSequenceNumber = 1;
82 extern void RemoveUnusedRegisters(void);
83 extern void BuildFlowTree(pBlock *pb);
84 extern void pCodeRegOptimizeRegUsage(void);
86 /****************************************************************/
87 /* Forward declarations */
88 /****************************************************************/
90 void unlinkpCode(pCode *pc);
92 static void genericAnalyze(pCode *pc);
93 static void AnalyzeGOTO(pCode *pc);
94 static void AnalyzeSKIP(pCode *pc);
95 static void AnalyzeRETURN(pCode *pc);
98 static void genericDestruct(pCode *pc);
99 static void genericPrint(FILE *of,pCode *pc);
101 static void pCodePrintLabel(FILE *of, pCode *pc);
102 static void pCodePrintFunction(FILE *of, pCode *pc);
103 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
104 static char *get_op_from_instruction( pCodeInstruction *pcc);
105 char *get_op( pCodeOp *pcop,char *buff,int buf_size);
106 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
107 int pCodePeepMatchRule(pCode *pc);
108 void pBlockStats(FILE *of, pBlock *pb);
109 pBlock *newpBlock(void);
110 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
111 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
112 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
113 void pCodeRegMapLiveRanges(pBlock *pb);
116 /****************************************************************/
117 /* PIC Instructions */
118 /****************************************************************/
120 pCodeInstruction pciADDWF = {
121 {PC_OPCODE, NULL, NULL, 0, NULL,
134 1,0, // dest, bit instruction
137 (PCC_W | PCC_REGISTER), // inCond
138 (PCC_REGISTER | PCC_Z) // outCond
141 pCodeInstruction pciADDFW = {
142 {PC_OPCODE, NULL, NULL, 0, NULL,
155 0,0, // dest, bit instruction
158 (PCC_W | PCC_REGISTER), // inCond
159 (PCC_W | PCC_Z) // outCond
162 pCodeInstruction pciADDLW = {
163 {PC_OPCODE, NULL, NULL, 0, NULL,
176 0,0, // dest, bit instruction
180 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
183 pCodeInstruction pciANDLW = {
184 {PC_OPCODE, NULL, NULL, 0, NULL,
197 0,0, // dest, bit instruction
201 (PCC_W | PCC_Z) // outCond
204 pCodeInstruction pciANDWF = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 1,0, // dest, bit instruction
221 (PCC_W | PCC_REGISTER), // inCond
222 (PCC_REGISTER | PCC_Z) // outCond
225 pCodeInstruction pciANDFW = {
226 {PC_OPCODE, NULL, NULL, 0, NULL,
239 0,0, // dest, bit instruction
242 (PCC_W | PCC_REGISTER), // inCond
243 (PCC_W | PCC_Z) // outCond
246 pCodeInstruction pciBCF = {
247 {PC_OPCODE, NULL, NULL, 0, NULL,
260 1,1, // dest, bit instruction
263 PCC_REGISTER, // inCond
264 PCC_REGISTER // outCond
267 pCodeInstruction pciBSF = {
268 {PC_OPCODE, NULL, NULL, 0, NULL,
281 1,1, // dest, bit instruction
284 PCC_REGISTER, // inCond
285 PCC_REGISTER // outCond
288 pCodeInstruction pciBTFSC = {
289 {PC_OPCODE, NULL, NULL, 0, NULL,
302 0,1, // dest, bit instruction
305 PCC_REGISTER, // inCond
309 pCodeInstruction pciBTFSS = {
310 {PC_OPCODE, NULL, NULL, 0, NULL,
323 0,1, // dest, bit instruction
326 PCC_REGISTER, // inCond
330 pCodeInstruction pciCALL = {
331 {PC_OPCODE, NULL, NULL, 0, NULL,
344 0,0, // dest, bit instruction
351 pCodeInstruction pciCOMF = {
352 {PC_OPCODE, NULL, NULL, 0, NULL,
365 1,0, // dest, bit instruction
368 PCC_REGISTER, // inCond
369 PCC_REGISTER // outCond
372 pCodeInstruction pciCOMFW = {
373 {PC_OPCODE, NULL, NULL, 0, NULL,
386 0,0, // dest, bit instruction
389 PCC_REGISTER, // inCond
393 pCodeInstruction pciCLRF = {
394 {PC_OPCODE, NULL, NULL, 0, NULL,
407 0,0, // dest, bit instruction
411 PCC_REGISTER // outCond
414 pCodeInstruction pciCLRW = {
415 {PC_OPCODE, NULL, NULL, 0, NULL,
428 0,0, // dest, bit instruction
435 pCodeInstruction pciDECF = {
436 {PC_OPCODE, NULL, NULL, 0, NULL,
449 1,0, // dest, bit instruction
452 PCC_REGISTER, // inCond
453 PCC_REGISTER // outCond
456 pCodeInstruction pciDECFW = {
457 {PC_OPCODE, NULL, NULL, 0, NULL,
470 0,0, // dest, bit instruction
473 PCC_REGISTER, // inCond
477 pCodeInstruction pciDECFSZ = {
478 {PC_OPCODE, NULL, NULL, 0, NULL,
491 1,0, // dest, bit instruction
494 PCC_REGISTER, // inCond
495 PCC_REGISTER // outCond
498 pCodeInstruction pciDECFSZW = {
499 {PC_OPCODE, NULL, NULL, 0, NULL,
512 0,0, // dest, bit instruction
515 PCC_REGISTER, // inCond
519 pCodeInstruction pciGOTO = {
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 0,0, // dest, bit instruction
540 pCodeInstruction pciINCF = {
541 {PC_OPCODE, NULL, NULL, 0, NULL,
554 1,0, // dest, bit instruction
557 PCC_REGISTER, // inCond
558 PCC_REGISTER // outCond
561 pCodeInstruction pciINCFW = {
562 {PC_OPCODE, NULL, NULL, 0, NULL,
575 0,0, // dest, bit instruction
578 PCC_REGISTER, // inCond
582 pCodeInstruction pciINCFSZ = {
583 {PC_OPCODE, NULL, NULL, 0, NULL,
596 1,0, // dest, bit instruction
599 PCC_REGISTER, // inCond
600 PCC_REGISTER // outCond
603 pCodeInstruction pciINCFSZW = {
604 {PC_OPCODE, NULL, NULL, 0, NULL,
617 0,0, // dest, bit instruction
620 PCC_REGISTER, // inCond
624 pCodeInstruction pciIORWF = {
625 {PC_OPCODE, NULL, NULL, 0, NULL,
638 1,0, // dest, bit instruction
641 (PCC_W | PCC_REGISTER), // inCond
642 (PCC_REGISTER | PCC_Z) // outCond
645 pCodeInstruction pciIORFW = {
646 {PC_OPCODE, NULL, NULL, 0, NULL,
659 0,0, // dest, bit instruction
662 (PCC_W | PCC_REGISTER), // inCond
663 (PCC_W | PCC_Z) // outCond
666 pCodeInstruction pciIORLW = {
667 {PC_OPCODE, NULL, NULL, 0, NULL,
680 0,0, // dest, bit instruction
684 (PCC_W | PCC_Z) // outCond
687 pCodeInstruction pciMOVF = {
688 {PC_OPCODE, NULL, NULL, 0, NULL,
701 1,0, // dest, bit instruction
704 PCC_REGISTER, // inCond
708 pCodeInstruction pciMOVFW = {
709 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,0, // dest, bit instruction
725 PCC_REGISTER, // inCond
726 (PCC_W | PCC_Z) // outCond
729 pCodeInstruction pciMOVWF = {
730 {PC_OPCODE, NULL, NULL, 0, NULL,
743 0,0, // dest, bit instruction
747 PCC_REGISTER // outCond
750 pCodeInstruction pciMOVLW = {
751 {PC_OPCODE, NULL, NULL, 0, NULL,
764 0,0, // dest, bit instruction
771 pCodeInstruction pciNOP = {
772 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
791 pCodeInstruction pciRETFIE = {
792 {PC_OPCODE, NULL, NULL, 0, NULL,
805 0,0, // dest, bit instruction
809 PCC_NONE // outCond (not true... affects the GIE bit too)
812 pCodeInstruction pciRETLW = {
813 {PC_OPCODE, NULL, NULL, 0, NULL,
826 0,0, // dest, bit instruction
833 pCodeInstruction pciRETURN = {
834 {PC_OPCODE, NULL, NULL, 0, NULL,
847 0,0, // dest, bit instruction
854 pCodeInstruction pciRLF = {
855 {PC_OPCODE, NULL, NULL, 0, NULL,
868 1,0, // dest, bit instruction
871 (PCC_C | PCC_REGISTER), // inCond
872 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
875 pCodeInstruction pciRLFW = {
876 {PC_OPCODE, NULL, NULL, 0, NULL,
889 0,0, // dest, bit instruction
892 (PCC_C | PCC_REGISTER), // inCond
893 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
896 pCodeInstruction pciRRF = {
897 {PC_OPCODE, NULL, NULL, 0, NULL,
910 1,0, // dest, bit instruction
913 (PCC_C | PCC_REGISTER), // inCond
914 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
917 pCodeInstruction pciRRFW = {
918 {PC_OPCODE, NULL, NULL, 0, NULL,
931 0,0, // dest, bit instruction
934 (PCC_C | PCC_REGISTER), // inCond
935 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
938 pCodeInstruction pciSUBWF = {
939 {PC_OPCODE, NULL, NULL, 0, NULL,
952 1,0, // dest, bit instruction
955 (PCC_W | PCC_REGISTER), // inCond
956 (PCC_REGISTER | PCC_Z) // outCond
959 pCodeInstruction pciSUBFW = {
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 0,0, // dest, bit instruction
976 (PCC_W | PCC_REGISTER), // inCond
977 (PCC_W | PCC_Z) // outCond
980 pCodeInstruction pciSUBLW = {
981 {PC_OPCODE, NULL, NULL, 0, NULL,
994 0,0, // dest, bit instruction
998 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1001 pCodeInstruction pciSWAPF = {
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1008 NULL, // from branch
1015 1,0, // dest, bit instruction
1016 0,0, // branch, skip
1018 (PCC_REGISTER), // inCond
1019 (PCC_REGISTER) // outCond
1022 pCodeInstruction pciSWAPFW = {
1023 {PC_OPCODE, NULL, NULL, 0, NULL,
1029 NULL, // from branch
1036 0,0, // dest, bit instruction
1037 0,0, // branch, skip
1039 (PCC_REGISTER), // inCond
1043 pCodeInstruction pciTRIS = {
1044 {PC_OPCODE, NULL, NULL, 0, NULL,
1050 NULL, // from branch
1057 0,0, // dest, bit instruction
1058 0,0, // branch, skip
1061 PCC_REGISTER // outCond
1064 pCodeInstruction pciXORWF = {
1065 {PC_OPCODE, NULL, NULL, 0, NULL,
1071 NULL, // from branch
1078 1,0, // dest, bit instruction
1079 0,0, // branch, skip
1081 (PCC_W | PCC_REGISTER), // inCond
1082 (PCC_REGISTER | PCC_Z) // outCond
1085 pCodeInstruction pciXORFW = {
1086 {PC_OPCODE, NULL, NULL, 0, NULL,
1092 NULL, // from branch
1099 0,0, // dest, bit instruction
1100 0,0, // branch, skip
1102 (PCC_W | PCC_REGISTER), // inCond
1103 (PCC_W | PCC_Z) // outCond
1106 pCodeInstruction pciXORLW = {
1107 {PC_OPCODE, NULL, NULL, 0, NULL,
1113 NULL, // from branch
1120 0,0, // dest, bit instruction
1121 0,0, // branch, skip
1124 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1128 #define MAX_PIC14MNEMONICS 100
1129 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1131 /* This definition needs to be part of configure.in */
1132 // #define USE_VSNPRINTF
1134 #ifdef USE_VSNPRINTF
1135 // Alas, vsnprintf is not ANSI standard, and does not exist
1136 // on Solaris (and probably other non-Gnu flavored Unixes).
1138 /*-----------------------------------------------------------------*/
1139 /* SAFE_snprintf - like snprintf except the string pointer is */
1140 /* after the string has been printed to. This is */
1141 /* useful for printing to string as though if it */
1142 /* were a stream. */
1143 /*-----------------------------------------------------------------*/
1144 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1152 va_start(val, format);
1154 vsnprintf(*str, *size, format, val);
1160 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1161 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1169 #else // USE_VSNPRINTF
1171 // This version is *not* safe, despite the name.
1173 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1177 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1182 va_start(val, format);
1184 vsprintf(buffer, format, val);
1187 len = strlen(buffer);
1189 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1190 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1193 strcpy(*str, buffer);
1199 #endif // USE_VSNPRINTF
1202 extern void initStack(int base_address, int size);
1203 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1204 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1205 extern void init_pic(char *);
1207 void pCodeInitRegisters(void)
1210 initStack(0xfff, 8);
1211 init_pic(port->processor);
1213 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1214 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1215 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1216 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1217 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1218 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1220 pc_status.rIdx = IDX_STATUS;
1221 pc_fsr.rIdx = IDX_FSR;
1222 pc_indf.rIdx = IDX_INDF;
1223 pc_intcon.rIdx = IDX_INTCON;
1224 pc_pcl.rIdx = IDX_PCL;
1225 pc_pclath.rIdx = IDX_PCLATH;
1227 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1228 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1229 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1231 pc_kzero.rIdx = IDX_KZ;
1232 pc_wsave.rIdx = IDX_WSAVE;
1233 pc_ssave.rIdx = IDX_SSAVE;
1235 /* probably should put this in a separate initialization routine */
1236 pb_dead_pcodes = newpBlock();
1240 /*-----------------------------------------------------------------*/
1241 /* mnem2key - convert a pic mnemonic into a hash key */
1242 /* (BTW - this spreads the mnemonics quite well) */
1244 /*-----------------------------------------------------------------*/
1246 int mnem2key(char const *mnem)
1255 key += toupper(*mnem++) +1;
1259 return (key & 0x1f);
1263 void pic14initMnemonics(void)
1268 pCodeInstruction *pci;
1270 if(mnemonics_initialized)
1273 //FIXME - probably should NULL out the array before making the assignments
1274 //since we check the array contents below this initialization.
1276 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1277 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1278 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1279 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1280 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1281 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1282 pic14Mnemonics[POC_BCF] = &pciBCF;
1283 pic14Mnemonics[POC_BSF] = &pciBSF;
1284 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1285 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1286 pic14Mnemonics[POC_CALL] = &pciCALL;
1287 pic14Mnemonics[POC_COMF] = &pciCOMF;
1288 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1289 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1290 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1291 pic14Mnemonics[POC_DECF] = &pciDECF;
1292 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1293 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1294 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1295 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1296 pic14Mnemonics[POC_INCF] = &pciINCF;
1297 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1298 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1299 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1300 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1301 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1302 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1303 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1304 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1305 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1306 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1307 pic14Mnemonics[POC_NOP] = &pciNOP;
1308 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1309 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1310 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1311 pic14Mnemonics[POC_RLF] = &pciRLF;
1312 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1313 pic14Mnemonics[POC_RRF] = &pciRRF;
1314 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1315 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1316 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1317 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1318 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1319 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1320 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1321 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1322 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1323 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1325 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1326 if(pic14Mnemonics[i])
1327 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1328 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1331 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1332 pci = hTabNextItem(pic14MnemonicsHash, &key);
1335 mnemonics_initialized = 1;
1338 int getpCodePeepCommand(char *cmd);
1340 int getpCode(char *mnem,unsigned dest)
1343 pCodeInstruction *pci;
1344 int key = mnem2key(mnem);
1346 if(!mnemonics_initialized)
1347 pic14initMnemonics();
1349 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1353 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1354 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1358 pci = hTabNextItemWK (pic14MnemonicsHash);
1365 /*-----------------------------------------------------------------*
1366 * pic14initpCodePeepCommands
1368 *-----------------------------------------------------------------*/
1369 void pic14initpCodePeepCommands(void)
1377 hTabAddItem(&pic14pCodePeepCommandsHash,
1378 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1380 } while (peepCommands[i].cmd);
1382 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1385 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1386 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1391 /*-----------------------------------------------------------------
1394 *-----------------------------------------------------------------*/
1396 int getpCodePeepCommand(char *cmd)
1400 int key = mnem2key(cmd);
1403 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1406 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1407 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1411 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1418 char getpBlock_dbName(pBlock *pb)
1424 return pb->cmemmap->dbName;
1428 void pBlockConvert2ISR(pBlock *pb)
1439 /*-----------------------------------------------------------------*/
1440 /* movepBlock2Head - given the dbname of a pBlock, move all */
1441 /* instances to the front of the doubly linked */
1442 /* list of pBlocks */
1443 /*-----------------------------------------------------------------*/
1445 void movepBlock2Head(char dbName)
1449 pb = the_pFile->pbHead;
1453 if(getpBlock_dbName(pb) == dbName) {
1454 pBlock *pbn = pb->next;
1455 pb->next = the_pFile->pbHead;
1456 the_pFile->pbHead->prev = pb;
1457 the_pFile->pbHead = pb;
1460 pb->prev->next = pbn;
1462 // If the pBlock that we just moved was the last
1463 // one in the link of all of the pBlocks, then we
1464 // need to point the tail to the block just before
1465 // the one we moved.
1466 // Note: if pb->next is NULL, then pb must have
1467 // been the last pBlock in the chain.
1470 pbn->prev = pb->prev;
1472 the_pFile->pbTail = pb->prev;
1483 void copypCode(FILE *of, char dbName)
1487 if(!of || !the_pFile)
1490 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1491 if(getpBlock_dbName(pb) == dbName) {
1498 void pcode_test(void)
1501 DFPRINTF((stderr,"pcode is alive!\n"));
1511 /* create the file name */
1512 strcpy(buffer,srcFileName);
1513 strcat(buffer,".p");
1515 if( !(pFile = fopen(buffer, "w" ))) {
1516 werror(E_FILE_OPEN_ERR,buffer);
1520 fprintf(pFile,"pcode dump\n\n");
1522 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1523 fprintf(pFile,"\n\tNew pBlock\n\n");
1525 fprintf(pFile,"%s",pb->cmemmap->sname);
1527 fprintf(pFile,"internal pblock");
1529 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1530 printpBlock(pFile,pb);
1534 /*-----------------------------------------------------------------*/
1535 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1536 /* ister, RegCond will return the bit being referenced. */
1538 /* fixme - why not just OR in the pcop bit field */
1539 /*-----------------------------------------------------------------*/
1541 static int RegCond(pCodeOp *pcop)
1547 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1548 switch(PCORB(pcop)->bit) {
1562 /*-----------------------------------------------------------------*/
1563 /* newpCode - create and return a newly initialized pCode */
1565 /* fixme - rename this */
1567 /* The purpose of this routine is to create a new Instruction */
1568 /* pCode. This is called by gen.c while the assembly code is being */
1572 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1573 /* (note that the op is analogous to but not the */
1574 /* same thing as the opcode of the instruction.) */
1575 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1578 /* a pointer to the new malloc'd pCode is returned. */
1582 /*-----------------------------------------------------------------*/
1583 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1585 pCodeInstruction *pci ;
1587 if(!mnemonics_initialized)
1588 pic14initMnemonics();
1590 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1592 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1593 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1596 if(pci->inCond == PCC_EXAMINE_PCOP)
1597 pci->inCond = RegCond(pcop);
1599 if(pci->outCond == PCC_EXAMINE_PCOP)
1600 pci->outCond = RegCond(pcop);
1602 pci->pc.prev = pci->pc.next = NULL;
1603 return (pCode *)pci;
1606 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1612 /*-----------------------------------------------------------------*/
1613 /* newpCodeWild - create a "wild" as in wild card pCode */
1615 /* Wild pcodes are used during the peep hole optimizer to serve */
1616 /* as place holders for any instruction. When a snippet of code is */
1617 /* compared to a peep hole rule, the wild card opcode will match */
1618 /* any instruction. However, the optional operand and label are */
1619 /* additional qualifiers that must also be matched before the */
1620 /* line (of assembly code) is declared matched. Note that the */
1621 /* operand may be wild too. */
1623 /* Note, a wild instruction is specified just like a wild var: */
1624 /* %4 ; A wild instruction, */
1625 /* See the peeph.def file for additional examples */
1627 /*-----------------------------------------------------------------*/
1629 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1634 pcw = Safe_calloc(1,sizeof(pCodeWild));
1636 pcw->pci.pc.type = PC_WILD;
1637 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1638 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1639 pcw->pci.pc.pb = NULL;
1641 // pcw->pci.pc.analyze = genericAnalyze;
1642 pcw->pci.pc.destruct = genericDestruct;
1643 pcw->pci.pc.print = genericPrint;
1645 pcw->id = pCodeID; // this is the 'n' in %n
1646 pcw->operand = optional_operand;
1647 pcw->label = optional_label;
1649 pcw->mustBeBitSkipInst = 0;
1650 pcw->mustNotBeBitSkipInst = 0;
1651 pcw->invertBitSkipInst = 0;
1653 return ( (pCode *)pcw);
1657 /*-----------------------------------------------------------------*/
1658 /* newPcodeInlineP - create a new pCode from a char string */
1659 /*-----------------------------------------------------------------*/
1662 pCode *newpCodeInlineP(char *cP)
1667 pcc = Safe_calloc(1,sizeof(pCodeComment));
1669 pcc->pc.type = PC_INLINE;
1670 pcc->pc.prev = pcc->pc.next = NULL;
1671 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1674 // pcc->pc.analyze = genericAnalyze;
1675 pcc->pc.destruct = genericDestruct;
1676 pcc->pc.print = genericPrint;
1679 pcc->comment = Safe_strdup(cP);
1681 pcc->comment = NULL;
1683 return ( (pCode *)pcc);
1687 /*-----------------------------------------------------------------*/
1688 /* newPcodeCharP - create a new pCode from a char string */
1689 /*-----------------------------------------------------------------*/
1691 pCode *newpCodeCharP(char *cP)
1696 pcc = Safe_calloc(1,sizeof(pCodeComment));
1698 pcc->pc.type = PC_COMMENT;
1699 pcc->pc.prev = pcc->pc.next = NULL;
1700 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1703 // pcc->pc.analyze = genericAnalyze;
1704 pcc->pc.destruct = genericDestruct;
1705 pcc->pc.print = genericPrint;
1708 pcc->comment = Safe_strdup(cP);
1710 pcc->comment = NULL;
1712 return ( (pCode *)pcc);
1716 /*-----------------------------------------------------------------*/
1717 /* newpCodeFunction - */
1718 /*-----------------------------------------------------------------*/
1721 pCode *newpCodeFunction(char *mod,char *f)
1725 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1726 //_ALLOC(pcf,sizeof(pCodeFunction));
1728 pcf->pc.type = PC_FUNCTION;
1729 pcf->pc.prev = pcf->pc.next = NULL;
1730 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1733 // pcf->pc.analyze = genericAnalyze;
1734 pcf->pc.destruct = genericDestruct;
1735 pcf->pc.print = pCodePrintFunction;
1740 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1741 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1742 strcpy(pcf->modname,mod);
1744 pcf->modname = NULL;
1747 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1748 pcf->fname = Safe_calloc(1,strlen(f)+1);
1749 strcpy(pcf->fname,f);
1753 return ( (pCode *)pcf);
1757 /*-----------------------------------------------------------------*/
1759 /*-----------------------------------------------------------------*/
1761 void destructpCodeFlow(pCode *pc)
1763 if(!pc || !isPCFL(pc))
1767 free(PCFL(pc)->uses);
1775 pCode *newpCodeFlow(void )
1779 //_ALLOC(pcflow,sizeof(pCodeFlow));
1780 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1782 pcflow->pc.type = PC_FLOW;
1783 pcflow->pc.prev = pcflow->pc.next = NULL;
1784 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1785 pcflow->pc.pb = NULL;
1787 // pcflow->pc.analyze = genericAnalyze;
1788 pcflow->pc.destruct = destructpCodeFlow;
1789 pcflow->pc.print = genericPrint;
1791 pcflow->pc.seq = GpcFlowSeq++;
1794 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1796 pcflow->from = pcflow->to = NULL;
1798 pcflow->inCond = PCC_NONE;
1799 pcflow->outCond = PCC_NONE;
1801 pcflow->firstBank = -1;
1802 pcflow->lastBank = -1;
1804 pcflow->FromConflicts = 0;
1805 pcflow->ToConflicts = 0;
1809 pcflow->registers = newSet();
1811 return ( (pCode *)pcflow);
1815 /*-----------------------------------------------------------------*/
1816 /*-----------------------------------------------------------------*/
1817 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1819 pCodeFlowLink *pcflowLink;
1821 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1823 pcflowLink->pcflow = pcflow;
1824 pcflowLink->bank_conflict = 0;
1829 /*-----------------------------------------------------------------*/
1830 /* newpCodeCSource - create a new pCode Source Symbol */
1831 /*-----------------------------------------------------------------*/
1833 pCode *newpCodeCSource(int ln, char *f, char *l)
1838 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1840 pccs->pc.type = PC_CSOURCE;
1841 pccs->pc.prev = pccs->pc.next = NULL;
1844 pccs->pc.destruct = genericDestruct;
1845 pccs->pc.print = genericPrint;
1847 pccs->line_number = ln;
1849 pccs->line = Safe_strdup(l);
1854 pccs->file_name = Safe_strdup(f);
1856 pccs->file_name = NULL;
1858 return ( (pCode *)pccs);
1861 /*-----------------------------------------------------------------*/
1862 /* pCodeLabelDestruct - free memory used by a label. */
1863 /*-----------------------------------------------------------------*/
1864 static void pCodeLabelDestruct(pCode *pc)
1870 if((pc->type == PC_LABEL) && PCL(pc)->label)
1871 free(PCL(pc)->label);
1877 pCode *newpCodeLabel(char *name, int key)
1883 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1885 pcl->pc.type = PC_LABEL;
1886 pcl->pc.prev = pcl->pc.next = NULL;
1887 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1890 // pcl->pc.analyze = genericAnalyze;
1891 pcl->pc.destruct = pCodeLabelDestruct;
1892 pcl->pc.print = pCodePrintLabel;
1898 sprintf(s,"_%05d_DS_",key);
1903 pcl->label = Safe_strdup(s);
1906 return ( (pCode *)pcl);
1911 /*-----------------------------------------------------------------*/
1912 /* newpBlock - create and return a pointer to a new pBlock */
1913 /*-----------------------------------------------------------------*/
1914 pBlock *newpBlock(void)
1919 PpB = Safe_calloc(1,sizeof(pBlock) );
1920 PpB->next = PpB->prev = NULL;
1922 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1923 PpB->tregisters = NULL;
1925 PpB->FlowTree = NULL;
1931 /*-----------------------------------------------------------------*/
1932 /* newpCodeChain - create a new chain of pCodes */
1933 /*-----------------------------------------------------------------*
1935 * This function will create a new pBlock and the pointer to the
1936 * pCode that is passed in will be the first pCode in the block.
1937 *-----------------------------------------------------------------*/
1940 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1943 pBlock *pB = newpBlock();
1945 pB->pcHead = pB->pcTail = pc;
1952 /*-----------------------------------------------------------------*/
1953 /* newpCodeOpLabel - Create a new label given the key */
1954 /* Note, a negative key means that the label is part of wild card */
1955 /* (and hence a wild card label) used in the pCodePeep */
1956 /* optimizations). */
1957 /*-----------------------------------------------------------------*/
1959 pCodeOp *newpCodeOpLabel(char *name, int key)
1962 static int label_key=-1;
1966 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1967 pcop->type = PO_LABEL;
1972 sprintf(s=buffer,"_%05d_DS_",key);
1974 s = name, key = label_key--;
1977 pcop->name = Safe_strdup(s);
1979 ((pCodeOpLabel *)pcop)->key = key;
1984 /*-----------------------------------------------------------------*/
1985 /*-----------------------------------------------------------------*/
1986 pCodeOp *newpCodeOpLit(int lit)
1992 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1993 pcop->type = PO_LITERAL;
1997 sprintf(s,"0x%02x",lit);
1999 pcop->name = Safe_strdup(s);
2002 ((pCodeOpLit *)pcop)->lit = lit;
2007 /*-----------------------------------------------------------------*/
2008 /*-----------------------------------------------------------------*/
2009 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2013 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2014 pcop->type = PO_IMMEDIATE;
2016 pcop->name = Safe_strdup(name);
2017 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2023 PCOI(pcop)->index = index;
2024 PCOI(pcop)->offset = offset;
2025 PCOI(pcop)->_const = code_space;
2030 /*-----------------------------------------------------------------*/
2031 /*-----------------------------------------------------------------*/
2032 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2038 if(!pcwb || !subtype) {
2039 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2043 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2044 pcop->type = PO_WILD;
2045 sprintf(s,"%%%d",id);
2046 pcop->name = Safe_strdup(s);
2048 PCOW(pcop)->id = id;
2049 PCOW(pcop)->pcwb = pcwb;
2050 PCOW(pcop)->subtype = subtype;
2051 PCOW(pcop)->matched = NULL;
2056 /*-----------------------------------------------------------------*/
2057 /*-----------------------------------------------------------------*/
2058 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2062 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2063 pcop->type = PO_GPR_BIT;
2065 pcop->name = Safe_strdup(s);
2069 PCORB(pcop)->bit = bit;
2070 PCORB(pcop)->inBitSpace = inBitSpace;
2075 /*-----------------------------------------------------------------*
2076 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2078 * If rIdx >=0 then a specific register from the set of registers
2079 * will be selected. If rIdx <0, then a new register will be searched
2081 *-----------------------------------------------------------------*/
2083 pCodeOp *newpCodeOpReg(int rIdx)
2087 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2092 PCOR(pcop)->rIdx = rIdx;
2093 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2095 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2098 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2099 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2102 pcop->type = PCOR(pcop)->r->pc_type;
2107 pCodeOp *newpCodeOpRegFromStr(char *name)
2111 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2112 PCOR(pcop)->r = allocRegByName(name, 1);
2113 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2114 pcop->type = PCOR(pcop)->r->pc_type;
2115 pcop->name = PCOR(pcop)->r->name;
2120 /*-----------------------------------------------------------------*/
2121 /*-----------------------------------------------------------------*/
2123 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2130 pcop = newpCodeOpBit(name, -1,0);
2134 pcop = newpCodeOpLit(-1);
2138 pcop = newpCodeOpLabel(NULL,-1);
2141 pcop = newpCodeOpReg(-1);
2145 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2148 pcop->name = Safe_strdup(name);
2156 /*-----------------------------------------------------------------*/
2157 /*-----------------------------------------------------------------*/
2158 void pCodeConstString(char *name, char *value)
2162 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2167 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2171 sprintf(buffer,"; %s = %s",name,value);
2173 addpCode2pBlock(pb,newpCodeCharP(buffer));
2174 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2177 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2183 /*-----------------------------------------------------------------*/
2184 /*-----------------------------------------------------------------*/
2185 void pCodeReadCodeTable(void)
2189 fprintf(stderr, " %s\n",__FUNCTION__);
2191 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2195 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2196 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2197 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2198 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2200 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2201 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2202 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2203 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2208 /*-----------------------------------------------------------------*/
2209 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2210 /*-----------------------------------------------------------------*/
2211 void addpCode2pBlock(pBlock *pb, pCode *pc)
2214 /* If this is the first pcode to be added to a block that
2215 * was initialized with a NULL pcode, then go ahead and
2216 * make this pcode the head and tail */
2217 pb->pcHead = pb->pcTail = pc;
2219 pb->pcTail->next = pc;
2220 pc->prev = pb->pcTail;
2227 /*-----------------------------------------------------------------*/
2228 /* addpBlock - place a pBlock into the pFile */
2229 /*-----------------------------------------------------------------*/
2230 void addpBlock(pBlock *pb)
2232 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2235 /* First time called, we'll pass through here. */
2236 //_ALLOC(the_pFile,sizeof(pFile));
2237 the_pFile = Safe_calloc(1,sizeof(pFile));
2238 the_pFile->pbHead = the_pFile->pbTail = pb;
2239 the_pFile->functions = NULL;
2243 the_pFile->pbTail->next = pb;
2244 pb->prev = the_pFile->pbTail;
2246 the_pFile->pbTail = pb;
2249 /*-----------------------------------------------------------------*/
2250 /* removepBlock - remove a pBlock from the pFile */
2251 /*-----------------------------------------------------------------*/
2252 void removepBlock(pBlock *pb)
2260 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2262 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2265 if(pbs == the_pFile->pbHead)
2266 the_pFile->pbHead = pbs->next;
2268 if (pbs == the_pFile->pbTail)
2269 the_pFile->pbTail = pbs->prev;
2272 pbs->next->prev = pbs->prev;
2275 pbs->prev->next = pbs->next;
2282 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2286 /*-----------------------------------------------------------------*/
2287 /* printpCode - write the contents of a pCode to a file */
2288 /*-----------------------------------------------------------------*/
2289 void printpCode(FILE *of, pCode *pc)
2300 fprintf(of,"warning - unable to print pCode\n");
2303 /*-----------------------------------------------------------------*/
2304 /* printpBlock - write the contents of a pBlock to a file */
2305 /*-----------------------------------------------------------------*/
2306 void printpBlock(FILE *of, pBlock *pb)
2316 for(pc = pb->pcHead; pc; pc = pc->next)
2321 /*-----------------------------------------------------------------*/
2323 /* pCode processing */
2327 /*-----------------------------------------------------------------*/
2329 void unlinkpCode(pCode *pc)
2335 fprintf(stderr,"Unlinking: ");
2336 printpCode(stderr, pc);
2339 pc->prev->next = pc->next;
2341 pc->next->prev = pc->prev;
2343 pc->prev = pc->next = NULL;
2347 /*-----------------------------------------------------------------*/
2348 /*-----------------------------------------------------------------*/
2350 static void genericDestruct(pCode *pc)
2356 /* For instructions, tell the register (if there's one used)
2357 * that it's no longer needed */
2358 regs *reg = getRegFromInstruction(pc);
2360 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2363 /* Instead of deleting the memory used by this pCode, mark
2364 * the object as bad so that if there's a pointer to this pCode
2365 * dangling around somewhere then (hopefully) when the type is
2366 * checked we'll catch it.
2371 addpCode2pBlock(pb_dead_pcodes, pc);
2378 /*-----------------------------------------------------------------*/
2379 /*-----------------------------------------------------------------*/
2380 void pBlockRegs(FILE *of, pBlock *pb)
2385 r = setFirstItem(pb->tregisters);
2387 r = setNextItem(pb->tregisters);
2392 /*-----------------------------------------------------------------*/
2393 /*-----------------------------------------------------------------*/
2394 char *get_op(pCodeOp *pcop,char *buffer, int size)
2399 int use_buffer = 1; // copy the string to the passed buffer pointer
2404 use_buffer = 0; // Don't bother copying the string to the buffer.
2408 switch(pcop->type) {
2412 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2415 return PCOR(pcop)->r->name;
2418 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2421 SAFE_snprintf(&buffer,&size,"%s",r->name);
2431 if(PCOI(pcop)->_const) {
2433 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2434 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2437 8 * PCOI(pcop)->offset );
2439 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2442 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2443 SAFE_snprintf(&s,&size,"(%s + %d)",
2445 PCOI(pcop)->index );
2447 SAFE_snprintf(&s,&size,"%s",pcop->name);
2454 //size = sizeof(buffer);
2455 if( PCOR(pcop)->instance) {
2456 SAFE_snprintf(&s,&size,"(%s + %d)",
2458 PCOR(pcop)->instance );
2459 //fprintf(stderr,"PO_DIR %s\n",buffer);
2461 SAFE_snprintf(&s,&size,"%s",pcop->name);
2467 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2476 return "NO operand";
2480 /*-----------------------------------------------------------------*/
2481 /*-----------------------------------------------------------------*/
2482 static char *get_op_from_instruction( pCodeInstruction *pcc)
2486 return get_op(pcc->pcop,NULL,0);
2488 return ("ERROR Null: "__FUNCTION__);
2492 /*-----------------------------------------------------------------*/
2493 /*-----------------------------------------------------------------*/
2494 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2497 fprintf(of,"pcodeopprint- not implemented\n");
2500 /*-----------------------------------------------------------------*/
2501 /*-----------------------------------------------------------------*/
2502 char *pCode2str(char *str, int size, pCode *pc)
2510 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2512 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2514 if(PCI(pc)->isBitInst) {
2515 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2516 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2517 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2518 PCI(pc)->pcop->name ,
2519 PCI(pc)->pcop->name );
2521 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2522 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2523 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2524 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2526 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2527 //PCI(pc)->pcop->t.bit );
2530 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2531 if( PCI(pc)->num_ops == 2)
2532 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2534 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2537 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2539 if( PCI(pc)->num_ops == 2)
2540 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2548 /* assuming that comment ends with a \n */
2549 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2553 /* assuming that inline code ends with a \n */
2554 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2558 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2561 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2564 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2567 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2570 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2574 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2581 /*-----------------------------------------------------------------*/
2582 /* genericPrint - the contents of a pCode to a file */
2583 /*-----------------------------------------------------------------*/
2584 static void genericPrint(FILE *of, pCode *pc)
2592 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2596 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2600 // If the opcode has a label, print that first
2602 pBranch *pbl = PCI(pc)->label;
2603 while(pbl && pbl->pc) {
2604 if(pbl->pc->type == PC_LABEL)
2605 pCodePrintLabel(of, pbl->pc);
2611 genericPrint(of,PCODE(PCI(pc)->cline));
2616 pCode2str(str, 256, pc);
2618 fprintf(of,"%s",str);
2621 fprintf(of, "\t;key=%03x",pc->seq);
2623 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2627 pBranch *dpb = pc->to; // debug
2629 switch ( dpb->pc->type) {
2631 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2634 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2637 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2640 fprintf(of, "\t;flow");
2654 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2655 if(PCW(pc)->pci.label)
2656 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2658 if(PCW(pc)->operand) {
2659 fprintf(of,";\toperand ");
2660 pCodeOpPrint(of,PCW(pc)->operand );
2665 fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2669 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2673 fprintf(of,"unknown pCode type %d\n",pc->type);
2678 /*-----------------------------------------------------------------*/
2679 /* pCodePrintFunction - prints function begin/end */
2680 /*-----------------------------------------------------------------*/
2682 static void pCodePrintFunction(FILE *of, pCode *pc)
2688 if( ((pCodeFunction *)pc)->modname)
2689 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2691 if(PCF(pc)->fname) {
2692 pBranch *exits = PCF(pc)->to;
2694 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2697 exits = exits->next;
2700 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2703 if((PCF(pc)->from &&
2704 PCF(pc)->from->pc->type == PC_FUNCTION &&
2705 PCF(PCF(pc)->from->pc)->fname) )
2706 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2708 fprintf(of,"; exit point [can't find entry point]\n");
2711 /*-----------------------------------------------------------------*/
2712 /* pCodePrintLabel - prints label */
2713 /*-----------------------------------------------------------------*/
2715 static void pCodePrintLabel(FILE *of, pCode *pc)
2722 fprintf(of,"%s\n",PCL(pc)->label);
2723 else if (PCL(pc)->key >=0)
2724 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2726 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2729 /*-----------------------------------------------------------------*/
2730 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2731 /* remove it if it is found. */
2732 /*-----------------------------------------------------------------*/
2733 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2740 if(pcl->type == PC_OPCODE)
2741 b = PCI(pcl)->label;
2743 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2748 //fprintf (stderr, "%s \n",__FUNCTION__);
2749 //pcl->print(stderr,pcl);
2750 //pc->print(stderr,pc);
2753 //fprintf (stderr, "found label\n");
2757 bprev->next = b->next; /* Not first pCode in chain */
2761 PCI(pcl)->label = b->next; /* First pCode in chain */
2764 return; /* A label can't occur more than once */
2772 /*-----------------------------------------------------------------*/
2773 /*-----------------------------------------------------------------*/
2774 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2790 /*-----------------------------------------------------------------*/
2791 /* pBranchLink - given two pcodes, this function will link them */
2792 /* together through their pBranches */
2793 /*-----------------------------------------------------------------*/
2794 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2798 // Declare a new branch object for the 'from' pCode.
2800 //_ALLOC(b,sizeof(pBranch));
2801 b = Safe_calloc(1,sizeof(pBranch));
2802 b->pc = PCODE(t); // The link to the 'to' pCode.
2805 f->to = pBranchAppend(f->to,b);
2807 // Now do the same for the 'to' pCode.
2809 //_ALLOC(b,sizeof(pBranch));
2810 b = Safe_calloc(1,sizeof(pBranch));
2814 t->from = pBranchAppend(t->from,b);
2819 /*-----------------------------------------------------------------*/
2820 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2822 /*-----------------------------------------------------------------*/
2823 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2836 /*-----------------------------------------------------------------*/
2837 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2838 /*-----------------------------------------------------------------*/
2839 static void pCodeUnlink(pCode *pc)
2844 if(!pc->prev || !pc->next) {
2845 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2849 /* first remove the pCode from the chain */
2850 pc->prev->next = pc->next;
2851 pc->next->prev = pc->prev;
2853 /* Now for the hard part... */
2855 /* Remove the branches */
2859 pc1 = pb1->pc; /* Get the pCode that branches to the
2860 * one we're unlinking */
2862 /* search for the link back to this pCode (the one we're
2864 if(pb2 = pBranchFind(pc1->to,pc)) {
2865 pb2->pc = pc->to->pc; // make the replacement
2867 /* if the pCode we're unlinking contains multiple 'to'
2868 * branches (e.g. this a skip instruction) then we need
2869 * to copy these extra branches to the chain. */
2871 pBranchAppend(pb2, pc->to->next);
2880 /*-----------------------------------------------------------------*/
2881 /*-----------------------------------------------------------------*/
2883 static void genericAnalyze(pCode *pc)
2893 // Go through the pCodes that are in pCode chain and link
2894 // them together through the pBranches. Note, the pCodes
2895 // are linked together as a contiguous stream like the
2896 // assembly source code lines. The linking here mimics this
2897 // except that comments are not linked in.
2899 pCode *npc = pc->next;
2901 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2902 pBranchLink(pc,npc);
2907 /* reached the end of the pcode chain without finding
2908 * an instruction we could link to. */
2912 fprintf(stderr,"analyze PC_FLOW\n");
2916 fprintf(stderr,,";A bad pCode is being used\n");
2922 /*-----------------------------------------------------------------*/
2923 /*-----------------------------------------------------------------*/
2924 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2928 if(pc->type == PC_LABEL) {
2929 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2932 if(pc->type == PC_OPCODE) {
2933 pbr = PCI(pc)->label;
2935 if(pbr->pc->type == PC_LABEL) {
2936 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2946 /*-----------------------------------------------------------------*/
2947 /*-----------------------------------------------------------------*/
2948 int checkLabel(pCode *pc)
2952 if(pc && isPCI(pc)) {
2953 pbr = PCI(pc)->label;
2955 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2965 /*-----------------------------------------------------------------*/
2966 /* findLabelinpBlock - Search the pCode for a particular label */
2967 /*-----------------------------------------------------------------*/
2968 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2975 for(pc = pb->pcHead; pc; pc = pc->next)
2976 if(compareLabel(pc,pcop_label))
2982 /*-----------------------------------------------------------------*/
2983 /* findLabel - Search the pCode for a particular label */
2984 /*-----------------------------------------------------------------*/
2985 pCode * findLabel(pCodeOpLabel *pcop_label)
2993 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2994 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2998 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3002 /*-----------------------------------------------------------------*/
3003 /* findNextpCode - given a pCode, find the next of type 'pct' */
3004 /* in the linked list */
3005 /*-----------------------------------------------------------------*/
3006 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3019 /*-----------------------------------------------------------------*/
3020 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3021 /* in the linked list */
3022 /*-----------------------------------------------------------------*/
3023 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3035 /*-----------------------------------------------------------------*/
3036 /* findNextInstruction - given a pCode, find the next instruction */
3037 /* in the linked list */
3038 /*-----------------------------------------------------------------*/
3039 pCode * findNextInstruction(pCode *pci)
3044 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3048 fprintf(stderr,"findNextInstruction: ");
3049 printpCode(stderr, pc);
3054 //fprintf(stderr,"Couldn't find instruction\n");
3058 /*-----------------------------------------------------------------*/
3059 /* findNextInstruction - given a pCode, find the next instruction */
3060 /* in the linked list */
3061 /*-----------------------------------------------------------------*/
3062 pCode * findPrevInstruction(pCode *pci)
3064 return findPrevpCode(pci, PC_OPCODE);
3067 /*-----------------------------------------------------------------*/
3068 /* findFunctionEnd - given a pCode find the end of the function */
3069 /* that contains it */
3070 /*-----------------------------------------------------------------*/
3071 pCode * findFunctionEnd(pCode *pc)
3075 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3081 fprintf(stderr,"Couldn't find function end\n");
3086 /*-----------------------------------------------------------------*/
3087 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3088 /* instruction with which it is associated. */
3089 /*-----------------------------------------------------------------*/
3090 static void AnalyzeLabel(pCode *pc)
3099 static void AnalyzeGOTO(pCode *pc)
3102 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3106 static void AnalyzeSKIP(pCode *pc)
3109 pBranchLink(pc,findNextInstruction(pc->next));
3110 pBranchLink(pc,findNextInstruction(pc->next->next));
3114 static void AnalyzeRETURN(pCode *pc)
3117 // branch_link(pc,findFunctionEnd(pc->next));
3123 /*-----------------------------------------------------------------*/
3124 /*-----------------------------------------------------------------*/
3125 regs * getRegFromInstruction(pCode *pc)
3130 PCI(pc)->num_ops == 0 )
3133 switch(PCI(pc)->pcop->type) {
3136 return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3140 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3141 return PCOR(PCI(pc)->pcop)->r;
3144 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3145 return NULL; // PCOR(PCI(pc)->pcop)->r;
3148 return PCOR(PCI(pc)->pcop)->r;
3151 //fprintf(stderr, "getRegFromInstruction - dir\n");
3152 return PCOR(PCI(pc)->pcop)->r;
3154 //fprintf(stderr, "getRegFromInstruction - literal\n");
3158 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3159 //genericPrint(stderr, pc);
3167 /*-----------------------------------------------------------------*/
3168 /*-----------------------------------------------------------------*/
3170 void AnalyzepBlock(pBlock *pb)
3177 /* Find all of the registers used in this pBlock
3178 * by looking at each instruction and examining it's
3181 for(pc = pb->pcHead; pc; pc = pc->next) {
3183 /* Is this an instruction with operands? */
3184 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3186 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3188 /* Loop through all of the registers declared so far in
3189 this block and see if we find this one there */
3191 regs *r = setFirstItem(pb->tregisters);
3194 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3195 PCOR(PCI(pc)->pcop)->r = r;
3198 r = setNextItem(pb->tregisters);
3202 /* register wasn't found */
3203 //r = Safe_calloc(1, sizeof(regs));
3204 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3205 //addSet(&pb->tregisters, r);
3206 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3207 //PCOR(PCI(pc)->pcop)->r = r;
3208 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3210 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3213 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3214 if(PCOR(PCI(pc)->pcop)->r) {
3215 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3216 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3218 if(PCI(pc)->pcop->name)
3219 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3221 fprintf(stderr,"ERROR: NULL register\n");
3230 /*-----------------------------------------------------------------*/
3232 /*-----------------------------------------------------------------*/
3233 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3235 void InsertpFlow(pCode *pc, pCode **pflow)
3237 PCFL(*pflow)->end = pc;
3239 if(!pc || !pc->next)
3242 *pflow = newpCodeFlow();
3243 pCodeInsertAfter(pc, *pflow);
3246 /*-----------------------------------------------------------------*/
3247 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3248 /* the flow blocks. */
3250 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3251 * point the instruction flow changes.
3253 /*-----------------------------------------------------------------*/
3254 void BuildFlow(pBlock *pb)
3257 pCode *last_pci=NULL;
3264 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3265 /* Insert a pCodeFlow object at the beginning of a pBlock */
3267 pflow = newpCodeFlow(); /* Create a new Flow object */
3268 pflow->next = pb->pcHead; /* Make the current head the next object */
3269 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3270 pb->pcHead = pflow; /* Make the Flow object the head */
3273 for( pc = findNextInstruction(pb->pcHead);
3275 pc=findNextInstruction(pc)) {
3278 PCI(pc)->pcflow = PCFL(pflow);
3280 //fprintf(stderr," build: ");
3281 //pflow->print(stderr,pflow);
3283 if( PCI(pc)->isSkip) {
3285 /* The two instructions immediately following this one
3286 * mark the beginning of a new flow segment */
3288 while(pc && PCI(pc)->isSkip) {
3290 PCI(pc)->pcflow = PCFL(pflow);
3294 InsertpFlow(pc, &pflow);
3295 pc=findNextInstruction(pc->next);
3303 PCI(pc)->pcflow = PCFL(pflow);
3305 InsertpFlow(pc, &pflow);
3307 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3309 InsertpFlow(pc, &pflow);
3312 } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3314 /* This instruction marks the beginning of a
3315 * new flow segment */
3319 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3321 PCI(pc)->pcflow = PCFL(pflow);
3328 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3329 PCFL(pflow)->end = pb->pcTail;
3332 /*-------------------------------------------------------------------*/
3333 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3334 /* the flow blocks. */
3336 * unBuildFlow removes pCodeFlow objects from a pCode chain
3338 /*-----------------------------------------------------------------*/
3339 void unBuildFlow(pBlock *pb)
3348 pCode *pcn = pc->next;
3352 PCI(pc)->pcflow = NULL;
3354 } else if(isPCFL(pc)) {
3364 /*-----------------------------------------------------------------*/
3365 /*-----------------------------------------------------------------*/
3366 void dumpCond(int cond)
3369 static char *pcc_str[] = {
3383 int ncond = sizeof(pcc_str) / sizeof(char *);
3386 fprintf(stderr, "0x%04X\n",cond);
3388 for(i=0,j=1; i<ncond; i++, j<<=1)
3390 fprintf(stderr, " %s\n",pcc_str[i]);
3394 /*-----------------------------------------------------------------*/
3395 /*-----------------------------------------------------------------*/
3396 void FlowStats(pCodeFlow *pcflow)
3404 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3406 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3409 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3414 fprintf(stderr, " FlowStats inCond: ");
3415 dumpCond(pcflow->inCond);
3416 fprintf(stderr, " FlowStats outCond: ");
3417 dumpCond(pcflow->outCond);
3421 /*-----------------------------------------------------------------*
3422 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3423 * if it affects the banking bits.
3425 * return: -1 == Banking bits are unaffected by this pCode.
3427 * return: > 0 == Banking bits are affected.
3429 * If the banking bits are affected, then the returned value describes
3430 * which bits are affected and how they're affected. The lower half
3431 * of the integer maps to the bits that are affected, the upper half
3432 * to whether they're set or cleared.
3434 *-----------------------------------------------------------------*/
3435 #define SET_BANK_BIT (1 << 16)
3436 #define CLR_BANK_BIT 0
3438 int isBankInstruction(pCode *pc)
3446 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3448 /* Check to see if the register banks are changing */
3449 if(PCI(pc)->isModReg) {
3451 pCodeOp *pcop = PCI(pc)->pcop;
3452 switch(PCI(pc)->op) {
3455 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3456 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3457 return SET_BANK_BIT | PIC_RP0_BIT;
3460 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3461 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3462 return CLR_BANK_BIT | PIC_RP0_BIT;
3467 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3468 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3469 return CLR_BANK_BIT | PIC_RP1_BIT;
3471 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3472 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3473 return CLR_BANK_BIT | PIC_RP1_BIT;
3477 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3478 //genericPrint(stderr, pc);
3489 /*-----------------------------------------------------------------*/
3490 /*-----------------------------------------------------------------*/
3491 void FillFlow(pCodeFlow *pcflow)
3500 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3502 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3505 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3512 isBankInstruction(pc);
3514 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3518 fprintf(stderr, " FillFlow - Bad end of flow\n");
3520 fprintf(stderr, " FillFlow - Ending flow with\n ");
3521 pc->print(stderr,pc);
3524 fprintf(stderr, " FillFlow inCond: ");
3525 dumpCond(pcflow->inCond);
3526 fprintf(stderr, " FillFlow outCond: ");
3527 dumpCond(pcflow->outCond);
3531 /*-----------------------------------------------------------------*/
3532 /*-----------------------------------------------------------------*/
3533 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3535 pCodeFlowLink *fromLink, *toLink;
3537 if(!from || !to || !to->pcflow || !from->pcflow)
3540 fromLink = newpCodeFlowLink(from->pcflow);
3541 toLink = newpCodeFlowLink(to->pcflow);
3543 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3544 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3548 /*-----------------------------------------------------------------*/
3549 /*-----------------------------------------------------------------*/
3550 void LinkFlow(pBlock *pb)
3556 //fprintf(stderr,"linkflow \n");
3558 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3560 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3563 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3565 //fprintf(stderr," link: ");
3566 //pcflow->print(stderr,pcflow);
3568 //FillFlow(PCFL(pcflow));
3570 pc = PCFL(pcflow)->end;
3572 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3573 if(isPCI_SKIP(pc)) {
3574 //fprintf(stderr, "ends with skip\n");
3575 //pc->print(stderr,pc);
3576 pct=findNextInstruction(pc->next);
3577 LinkFlow_pCode(PCI(pc),PCI(pct));
3578 pct=findNextInstruction(pct->next);
3579 LinkFlow_pCode(PCI(pc),PCI(pct));
3583 if(isPCI_BRANCH(pc)) {
3584 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3586 //fprintf(stderr, "ends with branch\n ");
3587 //pc->print(stderr,pc);
3589 if(!(pcol && isPCOLAB(pcol))) {
3590 if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3591 pc->print(stderr,pc);
3592 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3597 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3598 LinkFlow_pCode(PCI(pc),PCI(pct));
3600 fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3606 //fprintf(stderr, "ends with non-branching instruction:\n");
3607 //pc->print(stderr,pc);
3609 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3615 //fprintf(stderr, "ends with unknown\n");
3616 //pc->print(stderr,pc);
3620 //fprintf(stderr, "ends with nothing: ERROR\n");
3625 /*-----------------------------------------------------------------*/
3626 /*-----------------------------------------------------------------*/
3627 int isPCinFlow(pCode *pc, pCode *pcflow)
3633 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3636 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3642 /*-----------------------------------------------------------------*/
3643 /*-----------------------------------------------------------------*/
3644 void BanksUsedFlow2(pCode *pcflow)
3653 if(!isPCFL(pcflow)) {
3654 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3658 pc = findNextInstruction(pcflow->next);
3660 PCFL(pcflow)->lastBank = -1;
3662 while(isPCinFlow(pc,pcflow)) {
3664 int bank_selected = isBankInstruction(pc);
3666 //if(PCI(pc)->pcflow)
3667 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3669 if(bank_selected > 0) {
3670 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3672 /* This instruction is modifying banking bits before accessing registers */
3674 PCFL(pcflow)->firstBank = -1;
3676 if(PCFL(pcflow)->lastBank == -1)
3677 PCFL(pcflow)->lastBank = 0;
3679 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3680 if(bank_selected & SET_BANK_BIT)
3681 PCFL(pcflow)->lastBank |= bank;
3685 reg = getRegFromInstruction(pc);
3687 if(reg && !isREGinBank(reg, bank)) {
3688 int allbanks = REGallBanks(reg);
3690 PCFL(pcflow)->firstBank = allbanks;
3692 PCFL(pcflow)->lastBank = allbanks;
3699 pc = findNextInstruction(pc->next);
3702 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3703 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3708 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3710 void BanksUsedFlow(pBlock *pb)
3715 //pb->pcHead->print(stderr, pb->pcHead);
3717 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3718 //pcflow->print(stderr,pcflow);
3720 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3722 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3724 BanksUsedFlow2(pcflow);
3730 /*-----------------------------------------------------------------*/
3731 /*-----------------------------------------------------------------*/
3732 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3740 new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3742 new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3743 popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3745 pCodeInsertAfter(pc->prev, new_pc);
3747 /* Move the label, if there is one */
3749 if(PCI(pc)->label) {
3750 PCI(new_pc)->label = PCI(pc)->label;
3751 PCI(pc)->label = NULL;
3754 /* The new instruction has the same pcflow block */
3755 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3758 /*-----------------------------------------------------------------*/
3759 /*-----------------------------------------------------------------*/
3760 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3771 pc = findNextInstruction(pcfl->pc.next);
3773 while(isPCinFlow(pc,PCODE(pcfl))) {
3776 reg = getRegFromInstruction(pc);
3779 fprintf(stderr, " %s ",reg->name);
3780 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3785 if(reg && REG_BANK(reg)!=cur_bank) {
3786 /* Examine the instruction before this one to make sure it is
3787 * not a skip type instruction */
3788 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3789 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3790 int b = cur_bank ^ REG_BANK(reg);
3792 //fprintf(stderr, "Cool! can switch banks\n");
3793 cur_bank = REG_BANK(reg);
3798 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3801 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3802 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3806 insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3807 insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3809 insertBankSwitch(pc, -1, -1);
3812 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3813 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3814 pCodeInsertAfter(pc->prev, new_pc);
3815 if(PCI(pc)->label) {
3816 PCI(new_pc)->label = PCI(pc)->label;
3817 PCI(pc)->label = NULL;
3821 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3822 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3823 pCodeInsertAfter(pc, new_pc);
3829 //fprintf(stderr, "Bummer can't switch banks\n");
3835 pc = findNextInstruction(pc->next);
3839 if(pcprev && cur_bank) {
3840 /* Brute force - make sure that we point to bank 0 at the
3841 * end of each flow block */
3842 new_pc = newpCode(POC_BCF,
3843 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3844 pCodeInsertAfter(pcprev, new_pc);
3850 /*-----------------------------------------------------------------*/
3851 /*int compareBankFlow - compare the banking requirements between */
3853 /*-----------------------------------------------------------------*/
3854 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3857 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3860 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3863 if(pcflow->firstBank == -1)
3867 if(pcflowLink->pcflow->firstBank == -1) {
3868 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
3869 pcflowLink->pcflow->to :
3870 pcflowLink->pcflow->from);
3871 return compareBankFlow(pcflow, pctl, toORfrom);
3875 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3878 pcflowLink->bank_conflict++;
3879 pcflowLink->pcflow->FromConflicts++;
3880 pcflow->ToConflicts++;
3883 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3886 pcflowLink->bank_conflict++;
3887 pcflowLink->pcflow->ToConflicts++;
3888 pcflow->FromConflicts++;
3892 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3893 pcflowLink->pcflow->pc.seq,
3894 pcflowLink->pcflow->FromConflicts,
3895 pcflowLink->pcflow->ToConflicts);
3900 /*-----------------------------------------------------------------*/
3901 /*-----------------------------------------------------------------*/
3902 void FixBankFlow(pBlock *pb)
3906 pCodeFlowLink *pcfl;
3908 pCode *pcflow_max_To=NULL;
3909 pCode *pcflow_max_From=NULL;
3910 int max_ToConflicts=0;
3911 int max_FromConflicts=0;
3913 //fprintf(stderr,"Fix Bank flow \n");
3914 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3918 First loop through all of the flow objects in this pcode block
3919 and fix the ones that have banking conflicts between the
3923 //fprintf(stderr, "FixBankFlow - Phase 1\n");
3925 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3927 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3929 if(!isPCFL(pcflow)) {
3930 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3934 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
3935 PCFL(pcflow)->firstBank >= 0 &&
3936 PCFL(pcflow)->lastBank >= 0 ) {
3938 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3939 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3941 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3942 BanksUsedFlow2(pcflow);
3947 //fprintf(stderr, "FixBankFlow - Phase 2\n");
3949 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3951 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3956 if(!isPCFL(pcflow)) {
3957 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3961 PCFL(pcflow)->FromConflicts = 0;
3962 PCFL(pcflow)->ToConflicts = 0;
3967 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3968 pcfl = setFirstItem(PCFL(pcflow)->from);
3971 pc = PCODE(pcfl->pcflow);
3974 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3975 pc->print(stderr,pc);
3978 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3981 pcfl=setNextItem(PCFL(pcflow)->from);
3984 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3985 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3987 FixRegisterBankingInFlow(PCFL(pcflow),0);
3988 BanksUsedFlow2(pcflow);
3990 continue; /* Don't need to check the flow from here - it's already been fixed */
3997 pcfl = setFirstItem(PCFL(pcflow)->to);
4000 pc = PCODE(pcfl->pcflow);
4002 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4003 pc->print(stderr,pc);
4006 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4009 pcfl=setNextItem(PCFL(pcflow)->to);
4012 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4013 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4015 FixRegisterBankingInFlow(PCFL(pcflow),0);
4016 BanksUsedFlow2(pcflow);
4021 Loop through the flow objects again and find the ones with the
4025 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4027 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4029 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4030 pcflow_max_To = pcflow;
4032 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4033 pcflow_max_From = pcflow;
4037 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4038 PCFL(pcflow_max_To)->pc.seq,
4039 PCFL(pcflow_max_To)->ToConflicts);
4042 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4043 PCFL(pcflow_max_From)->pc.seq,
4044 PCFL(pcflow_max_From)->FromConflicts);
4048 /*-----------------------------------------------------------------*/
4049 /*-----------------------------------------------------------------*/
4050 void DumpFlow(pBlock *pb)
4054 pCodeFlowLink *pcfl;
4057 fprintf(stderr,"Dump flow \n");
4058 pb->pcHead->print(stderr, pb->pcHead);
4060 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4061 pcflow->print(stderr,pcflow);
4063 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4065 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4067 if(!isPCFL(pcflow)) {
4068 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4071 fprintf(stderr,"dumping: ");
4072 pcflow->print(stderr,pcflow);
4073 FlowStats(PCFL(pcflow));
4075 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4077 pc = PCODE(pcfl->pcflow);
4079 fprintf(stderr, " from seq %d:\n",pc->seq);
4081 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4082 pc->print(stderr,pc);
4087 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4089 pc = PCODE(pcfl->pcflow);
4091 fprintf(stderr, " to seq %d:\n",pc->seq);
4093 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4094 pc->print(stderr,pc);
4103 /*-----------------------------------------------------------------*/
4104 /*-----------------------------------------------------------------*/
4105 int OptimizepBlock(pBlock *pb)
4110 if(!pb || !peepOptimizing)
4113 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4115 for(pc = pb->pcHead; pc; pc = pc->next)
4116 matches += pCodePeepMatchRule(pc);
4119 pc = findNextInstruction(pb->pcHead);
4124 if(pCodePeepMatchRule(pc)) {
4129 pc = findNextInstruction(pcprev->next);
4131 pc = findNextInstruction(pb->pcHead);
4133 pc = findNextInstruction(pc->next);
4137 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4142 /*-----------------------------------------------------------------*/
4143 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4144 /*-----------------------------------------------------------------*/
4145 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4149 for(pc = pcs; pc; pc = pc->next) {
4151 if((pc->type == PC_OPCODE) &&
4153 (PCI(pc)->pcop->type == PO_LABEL) &&
4154 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4162 /*-----------------------------------------------------------------*/
4163 /*-----------------------------------------------------------------*/
4164 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4169 (PCI(pc)->pcop->type == PO_LABEL)) {
4171 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4173 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4175 free(pcol->pcop.name);
4177 sprintf(buffer,"_%05d_DS_",pcl->key);
4179 pcol->pcop.name = Safe_strdup(buffer);
4180 pcol->key = pcl->key;
4181 //pc->print(stderr,pc);
4188 /*-----------------------------------------------------------------*/
4189 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4190 /* pCode chain if they're not used. */
4191 /*-----------------------------------------------------------------*/
4192 void pBlockRemoveUnusedLabels(pBlock *pb)
4194 pCode *pc; pCodeLabel *pcl;
4199 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4201 pBranch *pbr = PCI(pc)->label;
4202 if(pbr && pbr->next) {
4203 pCode *pcd = pb->pcHead;
4205 //fprintf(stderr, "multiple labels\n");
4206 //pc->print(stderr,pc);
4211 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4212 //fprintf(stderr,"Used by:\n");
4213 //pcd->print(stderr,pcd);
4215 exchangeLabels(PCL(pbr->pc),pcd);
4224 for(pc = pb->pcHead; pc; pc = pc->next) {
4226 if(isPCL(pc)) // pc->type == PC_LABEL)
4228 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4229 pcl = PCL(PCI(pc)->label->pc);
4232 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4234 /* This pCode is a label, so search the pBlock to see if anyone
4237 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4238 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4239 /* Couldn't find an instruction that refers to this label
4240 * So, unlink the pCode label from it's pCode chain
4241 * and destroy the label */
4242 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4244 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4245 if(pc->type == PC_LABEL) {
4247 pCodeLabelDestruct(pc);
4249 unlinkpCodeFromBranch(pc, PCODE(pcl));
4250 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4261 /*-----------------------------------------------------------------*/
4262 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4263 /* chain and put them into pBranches that are */
4264 /* associated with the appropriate pCode */
4266 /*-----------------------------------------------------------------*/
4267 void pBlockMergeLabels(pBlock *pb)
4270 pCode *pc, *pcnext=NULL;
4275 /* First, Try to remove any unused labels */
4276 //pBlockRemoveUnusedLabels(pb);
4278 /* Now loop through the pBlock and merge the labels with the opcodes */
4280 for(pc = pb->pcHead; pc; pc = pc->next) {
4282 if(pc->type == PC_LABEL) {
4284 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4285 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4286 if((pcnext = findNextInstruction(pc) )) {
4288 pCode *pcn = pc->next;
4290 // Unlink the pCode label from it's pCode chain
4293 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4294 // And link it into the instruction's pBranch labels. (Note, since
4295 // it's possible to have multiple labels associated with one instruction
4296 // we must provide a means to accomodate the additional labels. Thus
4297 // the labels are placed into the singly-linked list "label" as
4298 // opposed to being a single member of the pCodeInstruction.)
4300 //_ALLOC(pbr,sizeof(pBranch));
4301 pbr = Safe_calloc(1,sizeof(pBranch));
4306 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4311 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4313 } else if(pc->type == PC_CSOURCE) {
4315 /* merge the source line symbolic info into the next instruction */
4316 if((pcnext = findNextInstruction(pc) )) {
4318 pCode *pcn = pc->next;
4320 // Unlink the pCode label from it's pCode chain
4322 PCI(pcnext)->cline = PCCS(pc);
4323 //fprintf(stderr, "merging CSRC\n");
4324 //genericPrint(stderr,pcnext);
4331 pBlockRemoveUnusedLabels(pb);
4335 /*-----------------------------------------------------------------*/
4336 /*-----------------------------------------------------------------*/
4337 int OptimizepCode(char dbName)
4339 #define MAX_PASSES 4
4348 DFPRINTF((stderr," Optimizing pCode\n"));
4352 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4353 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4354 matches += OptimizepBlock(pb);
4357 while(matches && ++passes < MAX_PASSES);
4362 /*-----------------------------------------------------------------*/
4363 /* popCopyGPR2Bit - copy a pcode operator */
4364 /*-----------------------------------------------------------------*/
4366 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4370 pcop = newpCodeOpBit(pc->name, bitval, 0);
4372 if( !( (pcop->type == PO_LABEL) ||
4373 (pcop->type == PO_LITERAL) ||
4374 (pcop->type == PO_STR) ))
4375 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4383 /*-----------------------------------------------------------------*/
4384 /*-----------------------------------------------------------------*/
4385 int InstructionRegBank(pCode *pc)
4389 if( (reg = getRegFromInstruction(pc)) == NULL)
4392 return REG_BANK(reg);
4397 /*-----------------------------------------------------------------*/
4398 /*-----------------------------------------------------------------*/
4399 void FixRegisterBanking(pBlock *pb)
4411 //pc = findNextpCode(pb->pcHead, PC_FLOW);
4412 pc = findNextpCode(pb->pcHead, PC_OPCODE);
4415 /* loop through all of the flow blocks with in one pblock */
4417 //fprintf(stderr,"Register banking\n");
4420 /* at this point, pc should point to a PC_FLOW object */
4423 /* for each flow block, determine the register banking
4428 //genericPrint(stderr, pc);
4430 reg = getRegFromInstruction(pc);
4433 fprintf(stderr, " %s ",reg->name);
4434 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4438 if(reg && REG_BANK(reg)!=cur_bank) {
4439 /* Examine the instruction before this one to make sure it is
4440 * not a skip type instruction */
4441 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4442 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4443 int b = cur_bank ^ REG_BANK(reg);
4445 //fprintf(stderr, "Cool! can switch banks\n");
4446 cur_bank = REG_BANK(reg);
4448 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4449 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4450 pCodeInsertAfter(pc->prev, new_pc);
4451 if(PCI(pc)->label) {
4452 PCI(new_pc)->label = PCI(pc)->label;
4453 PCI(pc)->label = NULL;
4456 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4457 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4458 pCodeInsertAfter(pc, new_pc);
4464 //fprintf(stderr, "Bummer can't switch banks\n");
4472 // } while(pc && !(isPCFL(pc)));
4477 if(pcprev && cur_bank) {
4478 /* Brute force - make sure that we point to bank 0 at the
4479 * end of each flow block */
4480 new_pc = newpCode(POC_BCF,
4481 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4482 pCodeInsertAfter(pcprev, new_pc);
4488 void pBlockDestruct(pBlock *pb)
4499 /*-----------------------------------------------------------------*/
4500 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4501 /* name dbName and combine them */
4502 /* into one block */
4503 /*-----------------------------------------------------------------*/
4504 void mergepBlocks(char dbName)
4507 pBlock *pb, *pbmerged = NULL,*pbn;
4509 pb = the_pFile->pbHead;
4511 //fprintf(stderr," merging blocks named %c\n",dbName);
4515 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4516 if( getpBlock_dbName(pb) == dbName) {
4518 //fprintf(stderr," merged block %c\n",dbName);
4523 addpCode2pBlock(pbmerged, pb->pcHead);
4524 /* addpCode2pBlock doesn't handle the tail: */
4525 pbmerged->pcTail = pb->pcTail;
4527 pb->prev->next = pbn;
4529 pbn->prev = pb->prev;
4534 //printpBlock(stderr, pbmerged);
4541 /*-----------------------------------------------------------------*/
4542 /* AnalyzeBanking - Called after the memory addresses have been */
4543 /* assigned to the registers. */
4545 /*-----------------------------------------------------------------*/
4546 void AnalyzeBanking(void)
4555 /* Phase 2 - Flow Analysis - Register Banking
4557 * In this phase, the individual flow blocks are examined
4558 * and register banking is fixed.
4561 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4562 //FixRegisterBanking(pb);
4564 /* Phase 2 - Flow Analysis
4566 * In this phase, the pCode is partition into pCodeFlow
4567 * blocks. The flow blocks mark the points where a continuous
4568 * stream of instructions changes flow (e.g. because of
4569 * a call or goto or whatever).
4572 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4576 /* Phase 2 - Flow Analysis - linking flow blocks
4578 * In this phase, the individual flow blocks are examined
4579 * to determine their order of excution.
4582 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4585 /* Phase 3 - Flow Analysis - Flow Tree
4587 * In this phase, the individual flow blocks are examined
4588 * to determine their order of excution.
4591 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4595 /* Phase x - Flow Analysis - Used Banks
4597 * In this phase, the individual flow blocks are examined
4598 * to determine the Register Banks they use
4601 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4604 /* Phase x - Flow Analysis - Used Banks
4606 * In this phase, the individual flow blocks are examined
4607 * to determine the Register Banks they use
4610 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4614 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4615 pCodeRegMapLiveRanges(pb);
4617 RemoveUnusedRegisters();
4619 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4620 pCodeRegOptimizeRegUsage();
4623 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4627 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4629 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4630 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4631 pcflow = pcflow->next) {
4633 FillFlow(PCFL(pcflow));
4637 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4639 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4640 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4641 pcflow = pcflow->next) {
4643 FlowStats(PCFL(pcflow));
4649 /*-----------------------------------------------------------------*/
4650 /* buildCallTree - look at the flow and extract all of the calls */
4652 /*-----------------------------------------------------------------*/
4653 set *register_usage(pBlock *pb);
4655 void buildCallTree(void )
4666 /* Now build the call tree.
4667 First we examine all of the pCodes for functions.
4668 Keep in mind that the function boundaries coincide
4669 with pBlock boundaries.
4671 The algorithm goes something like this:
4672 We have two nested loops. The outer loop iterates
4673 through all of the pBlocks/functions. The inner
4674 loop iterates through all of the pCodes for
4675 a given pBlock. When we begin iterating through
4676 a pBlock, the variable pc_fstart, pCode of the start
4677 of a function, is cleared. We then search for pCodes
4678 of type PC_FUNCTION. When one is encountered, we
4679 initialize pc_fstart to this and at the same time
4680 associate a new pBranch object that signifies a
4681 branch entry. If a return is found, then this signifies
4682 a function exit point. We'll link the pCodes of these
4683 returns to the matching pc_fstart.
4685 When we're done, a doubly linked list of pBranches
4686 will exist. The head of this list is stored in
4687 `the_pFile', which is the meta structure for all
4688 of the pCode. Look at the printCallTree function
4689 on how the pBranches are linked together.
4692 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4693 pCode *pc_fstart=NULL;
4694 for(pc = pb->pcHead; pc; pc = pc->next) {
4696 if (PCF(pc)->fname) {
4698 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4699 //fprintf(stderr," found main \n");
4700 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4704 pbr = Safe_calloc(1,sizeof(pBranch));
4705 pbr->pc = pc_fstart = pc;
4708 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4710 // Here's a better way of doing the same:
4711 addSet(&pb->function_entries, pc);
4714 // Found an exit point in a function, e.g. return
4715 // (Note, there may be more than one return per function)
4717 pBranchLink(PCF(pc_fstart), PCF(pc));
4719 addSet(&pb->function_exits, pc);
4721 } else if(isCALL(pc)) {
4722 addSet(&pb->function_calls,pc);
4727 /* Re-allocate the registers so that there are no collisions
4728 * between local variables when one function call another */
4731 // pic14_deallocateAllRegs();
4733 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4740 /*-----------------------------------------------------------------*/
4741 /* AnalyzepCode - parse the pCode that has been generated and form */
4742 /* all of the logical connections. */
4744 /* Essentially what's done here is that the pCode flow is */
4746 /*-----------------------------------------------------------------*/
4748 void AnalyzepCode(char dbName)
4759 /* Phase 1 - Register allocation and peep hole optimization
4761 * The first part of the analysis is to determine the registers
4762 * that are used in the pCode. Once that is done, the peep rules
4763 * are applied to the code. We continue to loop until no more
4764 * peep rule optimizations are found (or until we exceed the
4765 * MAX_PASSES threshold).
4767 * When done, the required registers will be determined.
4773 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4774 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4776 /* First, merge the labels with the instructions */
4777 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4778 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4780 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4781 //fprintf(stderr," analyze and merging block %c\n",dbName);
4782 pBlockMergeLabels(pb);
4785 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4789 changes = OptimizepCode(dbName);
4791 } while(changes && (i++ < MAX_PASSES));
4796 /*-----------------------------------------------------------------*/
4797 /* ispCodeFunction - returns true if *pc is the pCode of a */
4799 /*-----------------------------------------------------------------*/
4800 bool ispCodeFunction(pCode *pc)
4803 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4809 /*-----------------------------------------------------------------*/
4810 /* findFunction - Search for a function by name (given the name) */
4811 /* in the set of all functions that are in a pBlock */
4812 /* (note - I expect this to change because I'm planning to limit */
4813 /* pBlock's to just one function declaration */
4814 /*-----------------------------------------------------------------*/
4815 pCode *findFunction(char *fname)
4822 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4824 pc = setFirstItem(pb->function_entries);
4827 if((pc->type == PC_FUNCTION) &&
4829 (strcmp(fname, PCF(pc)->fname)==0))
4832 pc = setNextItem(pb->function_entries);
4840 void MarkUsedRegisters(set *regset)
4845 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4846 r2 = pic14_regWithIdx(r1->rIdx);
4852 void pBlockStats(FILE *of, pBlock *pb)
4858 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4860 // for now just print the first element of each set
4861 pc = setFirstItem(pb->function_entries);
4863 fprintf(of,";entry: ");
4866 pc = setFirstItem(pb->function_exits);
4868 fprintf(of,";has an exit\n");
4872 pc = setFirstItem(pb->function_calls);
4874 fprintf(of,";functions called:\n");
4877 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4878 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
4880 pc = setNextItem(pb->function_calls);
4884 r = setFirstItem(pb->tregisters);
4886 int n = elementsInSet(pb->tregisters);
4888 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4891 fprintf(of,"; %s\n",r->name);
4892 r = setNextItem(pb->tregisters);
4897 /*-----------------------------------------------------------------*/
4898 /*-----------------------------------------------------------------*/
4900 static void sequencepCode(void)
4906 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4908 pb->seq = GpCodeSequenceNumber+1;
4910 for( pc = pb->pcHead; pc; pc = pc->next)
4911 pc->seq = ++GpCodeSequenceNumber;
4917 /*-----------------------------------------------------------------*/
4918 /*-----------------------------------------------------------------*/
4919 set *register_usage(pBlock *pb)
4922 set *registers=NULL;
4923 set *registersInCallPath = NULL;
4925 /* check recursion */
4927 pc = setFirstItem(pb->function_entries);
4934 if(pc->type != PC_FUNCTION)
4935 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4937 pc = setFirstItem(pb->function_calls);
4938 for( ; pc; pc = setNextItem(pb->function_calls)) {
4940 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4941 char *dest = get_op_from_instruction(PCI(pc));
4943 pcn = findFunction(dest);
4945 registersInCallPath = register_usage(pcn->pb);
4947 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4952 pBlockStats(stderr,pb); // debug
4955 // Mark the registers in this block as used.
4957 MarkUsedRegisters(pb->tregisters);
4958 if(registersInCallPath) {
4959 /* registers were used in the functions this pBlock has called */
4960 /* so now, we need to see if these collide with the ones we are */
4963 regs *r1,*r2, *newreg;
4965 DFPRINTF((stderr,"comparing registers\n"));
4967 r1 = setFirstItem(registersInCallPath);
4970 r2 = setFirstItem(pb->tregisters);
4972 while(r2 && (r1->type != REG_STK)) {
4974 if(r2->rIdx == r1->rIdx) {
4975 newreg = pic14_findFreeReg(REG_GPR);
4979 DFPRINTF((stderr,"Bummer, no more registers.\n"));
4983 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4984 r1->rIdx, newreg->rIdx));
4985 r2->rIdx = newreg->rIdx;
4986 //if(r2->name) free(r2->name);
4988 r2->name = Safe_strdup(newreg->name);
4992 newreg->wasUsed = 1;
4994 r2 = setNextItem(pb->tregisters);
4997 r1 = setNextItem(registersInCallPath);
5000 /* Collisions have been resolved. Now free the registers in the call path */
5001 r1 = setFirstItem(registersInCallPath);
5003 if(r1->type != REG_STK) {
5004 newreg = pic14_regWithIdx(r1->rIdx);
5007 r1 = setNextItem(registersInCallPath);
5011 // MarkUsedRegisters(pb->registers);
5013 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5016 DFPRINTF((stderr,"returning regs\n"));
5018 DFPRINTF((stderr,"not returning regs\n"));
5020 DFPRINTF((stderr,"pBlock after register optim.\n"));
5021 pBlockStats(stderr,pb); // debug
5027 /*-----------------------------------------------------------------*/
5028 /* printCallTree - writes the call tree to a file */
5030 /*-----------------------------------------------------------------*/
5031 void pct2(FILE *of,pBlock *pb,int indent)
5035 // set *registersInCallPath = NULL;
5041 return; //recursion ?
5043 pc = setFirstItem(pb->function_entries);
5050 for(i=0;i<indent;i++) // Indentation
5053 if(pc->type == PC_FUNCTION)
5054 fprintf(of,"%s\n",PCF(pc)->fname);
5059 pc = setFirstItem(pb->function_calls);
5060 for( ; pc; pc = setNextItem(pb->function_calls)) {
5062 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5063 char *dest = get_op_from_instruction(PCI(pc));
5065 pcn = findFunction(dest);
5067 pct2(of,pcn->pb,indent+1);
5069 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5077 /*-----------------------------------------------------------------*/
5078 /* printCallTree - writes the call tree to a file */
5080 /*-----------------------------------------------------------------*/
5082 void printCallTree(FILE *of)
5094 fprintf(of, "\npBlock statistics\n");
5095 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5100 fprintf(of,"Call Tree\n");
5101 pbr = the_pFile->functions;
5105 if(!ispCodeFunction(pc))
5106 fprintf(of,"bug in call tree");
5109 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5111 while(pc->next && !ispCodeFunction(pc->next)) {
5113 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5114 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5122 fprintf(of,"\n**************\n\na better call tree\n");
5123 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5128 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5129 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5135 /*-----------------------------------------------------------------*/
5137 /*-----------------------------------------------------------------*/
5139 void InlineFunction(pBlock *pb)
5147 pc = setFirstItem(pb->function_calls);
5149 for( ; pc; pc = setNextItem(pb->function_calls)) {
5152 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5158 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5160 //fprintf(stderr,"Cool can inline:\n");
5161 //pcn->print(stderr,pcn);
5163 //fprintf(stderr,"recursive call Inline\n");
5164 InlineFunction(pcn->pb);
5165 //fprintf(stderr,"return from recursive call Inline\n");
5168 At this point, *pc points to a CALL mnemonic, and
5169 *pcn points to the function that is being called.
5171 To in-line this call, we need to remove the CALL
5172 and RETURN(s), and link the function pCode in with
5178 /* Remove the CALL */
5182 /* remove callee pBlock from the pBlock linked list */
5183 removepBlock(pcn->pb);
5191 /* Remove the Function pCode */
5192 pct = findNextInstruction(pcn->next);
5194 /* Link the function with the callee */
5195 pc->next = pcn->next;
5196 pcn->next->prev = pc;
5198 /* Convert the function name into a label */
5200 pbr = Safe_calloc(1,sizeof(pBranch));
5201 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5203 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5204 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5206 /* turn all of the return's except the last into goto's */
5207 /* check case for 2 instruction pBlocks */
5208 pce = findNextInstruction(pcn->next);
5210 pCode *pce_next = findNextInstruction(pce->next);
5212 if(pce_next == NULL) {
5213 /* found the last return */
5214 pCode *pc_call_next = findNextInstruction(pc_call->next);
5216 //fprintf(stderr,"found last return\n");
5217 //pce->print(stderr,pce);
5218 pce->prev->next = pc_call->next;
5219 pc_call->next->prev = pce->prev;
5220 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5230 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5236 /*-----------------------------------------------------------------*/
5238 /*-----------------------------------------------------------------*/
5240 void InlinepCode(void)
5249 if(!functionInlining)
5252 /* Loop through all of the function definitions and count the
5253 * number of times each one is called */
5254 //fprintf(stderr,"inlining %d\n",__LINE__);
5256 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5258 pc = setFirstItem(pb->function_calls);
5260 for( ; pc; pc = setNextItem(pb->function_calls)) {
5263 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5264 if(pcn && isPCF(pcn)) {
5265 PCF(pcn)->ncalled++;
5268 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5273 //fprintf(stderr,"inlining %d\n",__LINE__);
5275 /* Now, Loop through the function definitions again, but this
5276 * time inline those functions that have only been called once. */
5278 InlineFunction(the_pFile->pbHead);
5279 //fprintf(stderr,"inlining %d\n",__LINE__);
5281 for(pb = the_pFile->pbHead; pb; pb = pb->next)