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
39 // Eventually this will go into device dependent files:
40 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
41 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
42 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
43 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
44 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
45 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
47 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
48 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "W_SAVE"}, -1, NULL,0,NULL};
49 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "STATUS_SAVE"}, -1, NULL,0,NULL};
51 static int mnemonics_initialized = 0;
54 static hTab *pic14MnemonicsHash = NULL;
58 static pFile *the_pFile = NULL;
59 static int peepOptimizing = 0;
60 static int GpCodeSequenceNumber = 1;
61 static int GpcFlowSeq = 1;
63 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE))
64 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch)
65 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip)
66 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW))
67 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION))
68 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL))
69 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
71 /****************************************************************/
72 /* Forward declarations */
73 /****************************************************************/
75 static void unlinkPC(pCode *pc);
77 static void genericAnalyze(pCode *pc);
78 static void AnalyzeGOTO(pCode *pc);
79 static void AnalyzeSKIP(pCode *pc);
80 static void AnalyzeRETURN(pCode *pc);
83 static void genericDestruct(pCode *pc);
84 static void genericPrint(FILE *of,pCode *pc);
86 static void pCodePrintLabel(FILE *of, pCode *pc);
87 static void pCodePrintFunction(FILE *of, pCode *pc);
88 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
89 static char *get_op( pCodeInstruction *pcc);
90 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
91 int pCodePeepMatchRule(pCode *pc);
92 void pBlockStats(FILE *of, pBlock *pb);
93 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
95 pCodeInstruction pciADDWF = {
96 {PC_OPCODE, NULL, NULL, 0, NULL,
108 1,0, // dest, bit instruction
110 (PCC_W | PCC_REGISTER), // inCond
111 (PCC_REGISTER | PCC_Z) // outCond
114 pCodeInstruction pciADDFW = {
115 {PC_OPCODE, NULL, NULL, 0, NULL,
127 0,0, // dest, bit instruction
129 (PCC_W | PCC_REGISTER), // inCond
130 (PCC_W | PCC_Z) // outCond
133 pCodeInstruction pciADDLW = {
134 {PC_OPCODE, NULL, NULL, 0, NULL,
146 0,0, // dest, bit instruction
149 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
152 pCodeInstruction pciANDLW = {
153 {PC_OPCODE, NULL, NULL, 0, NULL,
165 0,0, // dest, bit instruction
168 (PCC_W | PCC_Z) // outCond
171 pCodeInstruction pciANDWF = {
172 {PC_OPCODE, NULL, NULL, 0, NULL,
184 1,0, // dest, bit instruction
186 (PCC_W | PCC_REGISTER), // inCond
187 (PCC_REGISTER | PCC_Z) // outCond
190 pCodeInstruction pciANDFW = {
191 {PC_OPCODE, NULL, NULL, 0, NULL,
203 0,0, // dest, bit instruction
205 (PCC_W | PCC_REGISTER), // inCond
206 (PCC_W | PCC_Z) // outCond
209 pCodeInstruction pciBCF = {
210 {PC_OPCODE, NULL, NULL, 0, NULL,
222 1,1, // dest, bit instruction
224 PCC_REGISTER, // inCond
225 PCC_REGISTER // outCond
228 pCodeInstruction pciBSF = {
229 {PC_OPCODE, NULL, NULL, 0, NULL,
241 1,1, // dest, bit instruction
243 PCC_REGISTER, // inCond
244 PCC_REGISTER // outCond
247 pCodeInstruction pciBTFSC = {
248 {PC_OPCODE, NULL, NULL, 0, NULL,
260 0,1, // dest, bit instruction
262 PCC_REGISTER, // inCond
266 pCodeInstruction pciBTFSS = {
267 {PC_OPCODE, NULL, NULL, 0, NULL,
279 0,1, // dest, bit instruction
281 PCC_REGISTER, // inCond
285 pCodeInstruction pciCALL = {
286 {PC_OPCODE, NULL, NULL, 0, NULL,
298 0,0, // dest, bit instruction
304 pCodeInstruction pciCOMF = {
305 {PC_OPCODE, NULL, NULL, 0, NULL,
317 1,0, // dest, bit instruction
319 PCC_REGISTER, // inCond
320 PCC_REGISTER // outCond
323 pCodeInstruction pciCOMFW = {
324 {PC_OPCODE, NULL, NULL, 0, NULL,
336 0,0, // dest, bit instruction
338 PCC_REGISTER, // inCond
342 pCodeInstruction pciCLRF = {
343 {PC_OPCODE, NULL, NULL, 0, NULL,
355 0,0, // dest, bit instruction
357 PCC_REGISTER, // inCond
358 PCC_REGISTER // outCond
361 pCodeInstruction pciCLRW = {
362 {PC_OPCODE, NULL, NULL, 0, NULL,
374 0,0, // dest, bit instruction
380 pCodeInstruction pciDECF = {
381 {PC_OPCODE, NULL, NULL, 0, NULL,
393 1,0, // dest, bit instruction
395 PCC_REGISTER, // inCond
396 PCC_REGISTER // outCond
399 pCodeInstruction pciDECFW = {
400 {PC_OPCODE, NULL, NULL, 0, NULL,
412 0,0, // dest, bit instruction
414 PCC_REGISTER, // inCond
418 pCodeInstruction pciDECFSZ = {
419 {PC_OPCODE, NULL, NULL, 0, NULL,
431 1,0, // dest, bit instruction
433 PCC_REGISTER, // inCond
434 PCC_REGISTER // outCond
437 pCodeInstruction pciDECFSZW = {
438 {PC_OPCODE, NULL, NULL, 0, NULL,
450 0,0, // dest, bit instruction
452 PCC_REGISTER, // inCond
456 pCodeInstruction pciGOTO = {
457 {PC_OPCODE, NULL, NULL, 0, NULL,
469 0,0, // dest, bit instruction
476 pCodeInstruction pciINCF = {
477 {PC_OPCODE, NULL, NULL, 0, NULL,
489 1,0, // dest, bit instruction
491 PCC_REGISTER, // inCond
492 PCC_REGISTER // outCond
495 pCodeInstruction pciINCFW = {
496 {PC_OPCODE, NULL, NULL, 0, NULL,
508 0,0, // dest, bit instruction
510 PCC_REGISTER, // inCond
514 pCodeInstruction pciINCFSZ = {
515 {PC_OPCODE, NULL, NULL, 0, NULL,
527 1,0, // dest, bit instruction
529 PCC_REGISTER, // inCond
530 PCC_REGISTER // outCond
533 pCodeInstruction pciINCFSZW = {
534 {PC_OPCODE, NULL, NULL, 0, NULL,
546 0,0, // dest, bit instruction
548 PCC_REGISTER, // inCond
552 pCodeInstruction pciIORWF = {
553 {PC_OPCODE, NULL, NULL, 0, NULL,
565 1,0, // dest, bit instruction
567 (PCC_W | PCC_REGISTER), // inCond
568 (PCC_REGISTER | PCC_Z) // outCond
571 pCodeInstruction pciIORFW = {
572 {PC_OPCODE, NULL, NULL, 0, NULL,
584 0,0, // dest, bit instruction
586 (PCC_W | PCC_REGISTER), // inCond
587 (PCC_W | PCC_Z) // outCond
590 pCodeInstruction pciIORLW = {
591 {PC_OPCODE, NULL, NULL, 0, NULL,
603 0,0, // dest, bit instruction
606 (PCC_W | PCC_Z) // outCond
609 pCodeInstruction pciMOVF = {
610 {PC_OPCODE, NULL, NULL, 0, NULL,
622 1,0, // dest, bit instruction
624 PCC_REGISTER, // inCond
628 pCodeInstruction pciMOVFW = {
629 {PC_OPCODE, NULL, NULL, 0, NULL,
641 0,0, // dest, bit instruction
643 PCC_REGISTER, // inCond
644 (PCC_W | PCC_Z) // outCond
647 pCodeInstruction pciMOVWF = {
648 {PC_OPCODE, NULL, NULL, 0, NULL,
660 0,0, // dest, bit instruction
663 PCC_REGISTER // outCond
666 pCodeInstruction pciMOVLW = {
667 {PC_OPCODE, NULL, NULL, 0, NULL,
679 0,0, // dest, bit instruction
685 pCodeInstruction pciNOP = {
686 {PC_OPCODE, NULL, NULL, 0, NULL,
697 0,0, // dest, bit instruction
703 pCodeInstruction pciRETFIE = {
704 {PC_OPCODE, NULL, NULL, 0, NULL,
716 0,0, // dest, bit instruction
719 PCC_NONE // outCond (not true... affects the GIE bit too)
722 pCodeInstruction pciRETLW = {
723 {PC_OPCODE, NULL, NULL, 0, NULL,
735 0,0, // dest, bit instruction
741 pCodeInstruction pciRETURN = {
742 {PC_OPCODE, NULL, NULL, 0, NULL,
754 0,0, // dest, bit instruction
760 pCodeInstruction pciRLF = {
761 {PC_OPCODE, NULL, NULL, 0, NULL,
773 1,0, // dest, bit instruction
775 (PCC_C | PCC_REGISTER), // inCond
776 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
779 pCodeInstruction pciRLFW = {
780 {PC_OPCODE, NULL, NULL, 0, NULL,
792 0,0, // dest, bit instruction
794 (PCC_C | PCC_REGISTER), // inCond
795 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
798 pCodeInstruction pciRRF = {
799 {PC_OPCODE, NULL, NULL, 0, NULL,
811 1,0, // dest, bit instruction
813 (PCC_C | PCC_REGISTER), // inCond
814 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
817 pCodeInstruction pciRRFW = {
818 {PC_OPCODE, NULL, NULL, 0, NULL,
830 0,0, // dest, bit instruction
832 (PCC_C | PCC_REGISTER), // inCond
833 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
836 pCodeInstruction pciSUBWF = {
837 {PC_OPCODE, NULL, NULL, 0, NULL,
849 1,0, // dest, bit instruction
851 (PCC_W | PCC_REGISTER), // inCond
852 (PCC_REGISTER | PCC_Z) // outCond
855 pCodeInstruction pciSUBFW = {
856 {PC_OPCODE, NULL, NULL, 0, NULL,
868 0,0, // dest, bit instruction
870 (PCC_W | PCC_REGISTER), // inCond
871 (PCC_W | PCC_Z) // outCond
874 pCodeInstruction pciSUBLW = {
875 {PC_OPCODE, NULL, NULL, 0, NULL,
887 0,0, // dest, bit instruction
890 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
893 pCodeInstruction pciSWAPF = {
894 {PC_OPCODE, NULL, NULL, 0, NULL,
906 1,0, // dest, bit instruction
908 (PCC_REGISTER), // inCond
909 (PCC_REGISTER) // outCond
912 pCodeInstruction pciSWAPFW = {
913 {PC_OPCODE, NULL, NULL, 0, NULL,
925 0,0, // dest, bit instruction
927 (PCC_REGISTER), // inCond
931 pCodeInstruction pciTRIS = {
932 {PC_OPCODE, NULL, NULL, 0, NULL,
944 0,0, // dest, bit instruction
947 PCC_REGISTER // outCond
950 pCodeInstruction pciXORWF = {
951 {PC_OPCODE, NULL, NULL, 0, NULL,
963 1,0, // dest, bit instruction
965 (PCC_W | PCC_REGISTER), // inCond
966 (PCC_REGISTER | PCC_Z) // outCond
969 pCodeInstruction pciXORFW = {
970 {PC_OPCODE, NULL, NULL, 0, NULL,
982 0,0, // dest, bit instruction
984 (PCC_W | PCC_REGISTER), // inCond
985 (PCC_W | PCC_Z) // outCond
988 pCodeInstruction pciXORLW = {
989 {PC_OPCODE, NULL, NULL, 0, NULL,
1001 0,0, // dest, bit instruction
1002 0,0, // branch, skip
1004 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1008 #define MAX_PIC14MNEMONICS 100
1009 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1011 /* This definition needs to be part of configure.in */
1012 // #define USE_VSNPRINTF
1014 #ifdef USE_VSNPRINTF
1015 // Alas, vsnprintf is not ANSI standard, and does not exist
1016 // on Solaris (and probably other non-Gnu flavored Unixes).
1018 /*-----------------------------------------------------------------*/
1019 /* SAFE_snprintf - like snprintf except the string pointer is */
1020 /* after the string has been printed to. This is */
1021 /* useful for printing to string as though if it */
1022 /* were a stream. */
1023 /*-----------------------------------------------------------------*/
1024 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1032 va_start(val, format);
1034 vsnprintf(*str, *size, format, val);
1040 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1048 #else // USE_VSNPRINTF
1050 // This version is *not* safe, despite the name.
1052 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1056 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1061 va_start(val, format);
1063 vsprintf(buffer, format, val);
1066 len = strlen(buffer);
1068 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1071 strcpy(*str, buffer);
1077 #endif // USE_VSNPRINTF
1080 extern void initStack(int base_address, int size);
1081 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1082 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1083 extern void init_pic(void);
1085 void pCodeInitRegisters(void)
1091 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1092 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1093 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1094 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1095 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1096 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1098 pc_status.rIdx = IDX_STATUS;
1099 pc_fsr.rIdx = IDX_FSR;
1100 pc_indf.rIdx = IDX_INDF;
1101 pc_intcon.rIdx = IDX_INTCON;
1102 pc_pcl.rIdx = IDX_PCL;
1103 pc_pclath.rIdx = IDX_PCLATH;
1105 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1106 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1107 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1109 pc_kzero.rIdx = IDX_KZ;
1110 pc_wsave.rIdx = IDX_WSAVE;
1111 pc_ssave.rIdx = IDX_SSAVE;
1115 /*-----------------------------------------------------------------*/
1116 /* mnem2key - convert a pic mnemonic into a hash key */
1117 /* (BTW - this spreads the mnemonics quite well) */
1119 /*-----------------------------------------------------------------*/
1121 int mnem2key(char const *mnem)
1130 key += toupper(*mnem++) +1;
1134 return (key & 0x1f);
1138 void pic14initMnemonics(void)
1143 pCodeInstruction *pci;
1145 if(mnemonics_initialized)
1148 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1149 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1150 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1151 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1152 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1153 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1154 pic14Mnemonics[POC_BCF] = &pciBCF;
1155 pic14Mnemonics[POC_BSF] = &pciBSF;
1156 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1157 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1158 pic14Mnemonics[POC_CALL] = &pciCALL;
1159 pic14Mnemonics[POC_COMF] = &pciCOMF;
1160 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1161 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1162 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1163 pic14Mnemonics[POC_DECF] = &pciDECF;
1164 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1165 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1166 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1167 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1168 pic14Mnemonics[POC_INCF] = &pciINCF;
1169 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1170 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1171 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1172 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1173 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1174 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1175 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1176 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1177 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1178 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1179 pic14Mnemonics[POC_NOP] = &pciNOP;
1180 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1181 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1182 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1183 pic14Mnemonics[POC_RLF] = &pciRLF;
1184 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1185 pic14Mnemonics[POC_RRF] = &pciRRF;
1186 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1187 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1188 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1189 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1190 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1191 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1192 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1193 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1194 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1195 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1197 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1198 if(pic14Mnemonics[i])
1199 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1200 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1203 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1204 pci = hTabNextItem(pic14MnemonicsHash, &key);
1207 mnemonics_initialized = 1;
1210 int getpCode(char *mnem,unsigned dest)
1213 pCodeInstruction *pci;
1214 int key = mnem2key(mnem);
1216 if(!mnemonics_initialized)
1217 pic14initMnemonics();
1219 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1223 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1224 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1228 pci = hTabNextItemWK (pic14MnemonicsHash);
1235 char getpBlock_dbName(pBlock *pb)
1241 return pb->cmemmap->dbName;
1245 void pBlockConvert2ISR(pBlock *pb)
1256 /*-----------------------------------------------------------------*/
1257 /* movepBlock2Head - given the dbname of a pBlock, move all */
1258 /* instances to the front of the doubly linked */
1259 /* list of pBlocks */
1260 /*-----------------------------------------------------------------*/
1262 void movepBlock2Head(char dbName)
1266 pb = the_pFile->pbHead;
1270 if(getpBlock_dbName(pb) == dbName) {
1271 pBlock *pbn = pb->next;
1272 pb->next = the_pFile->pbHead;
1273 the_pFile->pbHead->prev = pb;
1274 the_pFile->pbHead = pb;
1277 pb->prev->next = pbn;
1279 // If the pBlock that we just moved was the last
1280 // one in the link of all of the pBlocks, then we
1281 // need to point the tail to the block just before
1282 // the one we moved.
1283 // Note: if pb->next is NULL, then pb must have
1284 // been the last pBlock in the chain.
1287 pbn->prev = pb->prev;
1289 the_pFile->pbTail = pb->prev;
1300 void copypCode(FILE *of, char dbName)
1304 if(!of || !the_pFile)
1307 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1308 if(getpBlock_dbName(pb) == dbName) {
1315 void pcode_test(void)
1318 DFPRINTF((stderr,"pcode is alive!\n"));
1328 /* create the file name */
1329 strcpy(buffer,srcFileName);
1330 strcat(buffer,".p");
1332 if( !(pFile = fopen(buffer, "w" ))) {
1333 werror(E_FILE_OPEN_ERR,buffer);
1337 fprintf(pFile,"pcode dump\n\n");
1339 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1340 fprintf(pFile,"\n\tNew pBlock\n\n");
1342 fprintf(pFile,"%s",pb->cmemmap->sname);
1344 fprintf(pFile,"internal pblock");
1346 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1347 printpBlock(pFile,pb);
1351 /*-----------------------------------------------------------------*/
1352 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1353 /* ister, RegCond will return the bit being referenced. */
1355 /* fixme - why not just OR in the pcop bit field */
1356 /*-----------------------------------------------------------------*/
1358 static int RegCond(pCodeOp *pcop)
1364 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1365 switch(PCORB(pcop)->bit) {
1379 /*-----------------------------------------------------------------*/
1380 /* newpCode - create and return a newly initialized pCode */
1382 /* fixme - rename this */
1384 /* The purpose of this routine is to create a new Instruction */
1385 /* pCode. This is called by gen.c while the assembly code is being */
1389 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1390 /* (note that the op is analogous to but not the */
1391 /* same thing as the opcode of the instruction.) */
1392 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1395 /* a pointer to the new malloc'd pCode is returned. */
1399 /*-----------------------------------------------------------------*/
1400 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1402 pCodeInstruction *pci ;
1404 if(!mnemonics_initialized)
1405 pic14initMnemonics();
1407 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1409 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1410 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1413 if(pci->inCond == PCC_EXAMINE_PCOP)
1414 pci->inCond = RegCond(pcop);
1416 if(pci->outCond == PCC_EXAMINE_PCOP)
1417 pci->outCond = RegCond(pcop);
1419 pci->pc.prev = pci->pc.next = NULL;
1420 return (pCode *)pci;
1423 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1429 /*-----------------------------------------------------------------*/
1430 /* newpCodeWild - create a "wild" as in wild card pCode */
1432 /* Wild pcodes are used during the peep hole optimizer to serve */
1433 /* as place holders for any instruction. When a snippet of code is */
1434 /* compared to a peep hole rule, the wild card opcode will match */
1435 /* any instruction. However, the optional operand and label are */
1436 /* additional qualifiers that must also be matched before the */
1437 /* line (of assembly code) is declared matched. Note that the */
1438 /* operand may be wild too. */
1440 /* Note, a wild instruction is specified just like a wild var: */
1441 /* %4 ; A wild instruction, */
1442 /* See the peeph.def file for additional examples */
1444 /*-----------------------------------------------------------------*/
1446 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1451 pcw = Safe_calloc(1,sizeof(pCodeWild));
1453 pcw->pci.pc.type = PC_WILD;
1454 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1455 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1456 pcw->pci.pc.pb = NULL;
1458 // pcw->pci.pc.analyze = genericAnalyze;
1459 pcw->pci.pc.destruct = genericDestruct;
1460 pcw->pci.pc.print = genericPrint;
1462 pcw->id = pCodeID; // this is the 'n' in %n
1463 pcw->operand = optional_operand;
1464 pcw->label = optional_label;
1466 return ( (pCode *)pcw);
1470 /*-----------------------------------------------------------------*/
1471 /* newPcodeCharP - create a new pCode from a char string */
1472 /*-----------------------------------------------------------------*/
1474 pCode *newpCodeCharP(char *cP)
1479 pcc = Safe_calloc(1,sizeof(pCodeComment));
1481 pcc->pc.type = PC_COMMENT;
1482 pcc->pc.prev = pcc->pc.next = NULL;
1483 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1486 // pcc->pc.analyze = genericAnalyze;
1487 pcc->pc.destruct = genericDestruct;
1488 pcc->pc.print = genericPrint;
1491 pcc->comment = Safe_strdup(cP);
1493 pcc->comment = NULL;
1495 return ( (pCode *)pcc);
1499 /*-----------------------------------------------------------------*/
1500 /* newpCodeFunction - */
1501 /*-----------------------------------------------------------------*/
1504 pCode *newpCodeFunction(char *mod,char *f)
1508 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1509 //_ALLOC(pcf,sizeof(pCodeFunction));
1511 pcf->pc.type = PC_FUNCTION;
1512 pcf->pc.prev = pcf->pc.next = NULL;
1513 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1516 // pcf->pc.analyze = genericAnalyze;
1517 pcf->pc.destruct = genericDestruct;
1518 pcf->pc.print = pCodePrintFunction;
1521 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1522 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1523 strcpy(pcf->modname,mod);
1525 pcf->modname = NULL;
1528 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1529 pcf->fname = Safe_calloc(1,strlen(f)+1);
1530 strcpy(pcf->fname,f);
1534 return ( (pCode *)pcf);
1538 /*-----------------------------------------------------------------*/
1540 /*-----------------------------------------------------------------*/
1543 pCode *newpCodeFlow(void )
1547 //_ALLOC(pcflow,sizeof(pCodeFlow));
1548 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1550 pcflow->pc.type = PC_FLOW;
1551 pcflow->pc.prev = pcflow->pc.next = NULL;
1552 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1553 pcflow->pc.pb = NULL;
1555 // pcflow->pc.analyze = genericAnalyze;
1556 pcflow->pc.destruct = genericDestruct;
1557 pcflow->pc.print = genericPrint;
1559 pcflow->pc.seq = GpcFlowSeq++;
1562 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1564 pcflow->from = pcflow->to = NULL;
1566 pcflow->inCond = PCC_NONE;
1567 pcflow->outCond = PCC_NONE;
1570 return ( (pCode *)pcflow);
1574 /*-----------------------------------------------------------------*/
1575 /* pCodeLabelDestruct - free memory used by a label. */
1576 /*-----------------------------------------------------------------*/
1577 static void pCodeLabelDestruct(pCode *pc)
1583 if((pc->type == PC_LABEL) && PCL(pc)->label)
1584 free(PCL(pc)->label);
1590 pCode *newpCodeLabel(char *name, int key)
1596 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1598 pcl->pc.type = PC_LABEL;
1599 pcl->pc.prev = pcl->pc.next = NULL;
1600 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1603 // pcl->pc.analyze = genericAnalyze;
1604 pcl->pc.destruct = pCodeLabelDestruct;
1605 pcl->pc.print = pCodePrintLabel;
1611 sprintf(s,"_%05d_DS_",key);
1616 pcl->label = Safe_strdup(s);
1619 return ( (pCode *)pcl);
1624 /*-----------------------------------------------------------------*/
1625 /* newpBlock - create and return a pointer to a new pBlock */
1626 /*-----------------------------------------------------------------*/
1627 pBlock *newpBlock(void)
1632 PpB = Safe_calloc(1,sizeof(pBlock) );
1633 PpB->next = PpB->prev = NULL;
1635 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1636 PpB->tregisters = NULL;
1643 /*-----------------------------------------------------------------*/
1644 /* newpCodeChain - create a new chain of pCodes */
1645 /*-----------------------------------------------------------------*
1647 * This function will create a new pBlock and the pointer to the
1648 * pCode that is passed in will be the first pCode in the block.
1649 *-----------------------------------------------------------------*/
1652 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1655 pBlock *pB = newpBlock();
1657 pB->pcHead = pB->pcTail = pc;
1664 /*-----------------------------------------------------------------*/
1665 /* newpCodeOpLabel - Create a new label given the key */
1666 /* Note, a negative key means that the label is part of wild card */
1667 /* (and hence a wild card label) used in the pCodePeep */
1668 /* optimizations). */
1669 /*-----------------------------------------------------------------*/
1671 pCodeOp *newpCodeOpLabel(char *name, int key)
1674 static int label_key=-1;
1678 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1679 pcop->type = PO_LABEL;
1684 sprintf(s=buffer,"_%05d_DS_",key);
1686 s = name, key = label_key--;
1689 pcop->name = Safe_strdup(s);
1691 ((pCodeOpLabel *)pcop)->key = key;
1696 /*-----------------------------------------------------------------*/
1697 /*-----------------------------------------------------------------*/
1698 pCodeOp *newpCodeOpLit(int lit)
1704 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1705 pcop->type = PO_LITERAL;
1709 sprintf(s,"0x%02x",lit);
1711 pcop->name = Safe_strdup(s);
1714 ((pCodeOpLit *)pcop)->lit = lit;
1719 /*-----------------------------------------------------------------*/
1720 /*-----------------------------------------------------------------*/
1721 pCodeOp *newpCodeOpImmd(char *name, int offset)
1726 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1727 pcop->type = PO_IMMEDIATE;
1729 pcop->name = Safe_strdup(name);
1735 PCOI(pcop)->offset = offset;
1740 /*-----------------------------------------------------------------*/
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1748 if(!pcp || !subtype) {
1749 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1753 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1754 pcop->type = PO_WILD;
1755 sprintf(s,"%%%d",id);
1756 pcop->name = Safe_strdup(s);
1758 PCOW(pcop)->id = id;
1759 PCOW(pcop)->pcp = pcp;
1760 PCOW(pcop)->subtype = subtype;
1761 PCOW(pcop)->matched = NULL;
1766 /*-----------------------------------------------------------------*/
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1772 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1773 pcop->type = PO_GPR_BIT;
1775 pcop->name = Safe_strdup(s);
1779 PCORB(pcop)->bit = bit;
1780 PCORB(pcop)->inBitSpace = inBitSpace;
1785 pCodeOp *newpCodeOpReg(int rIdx)
1789 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1792 PCOR(pcop)->rIdx = rIdx;
1793 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1794 pcop->type = PCOR(pcop)->r->pc_type;
1798 pCodeOp *newpCodeOpRegFromStr(char *name)
1802 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1803 PCOR(pcop)->r = allocRegByName(name);
1804 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1805 pcop->type = PCOR(pcop)->r->pc_type;
1806 pcop->name = PCOR(pcop)->r->name;
1811 /*-----------------------------------------------------------------*/
1812 /*-----------------------------------------------------------------*/
1814 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1821 pcop = newpCodeOpBit(name, -1,0);
1825 pcop = newpCodeOpLit(-1);
1829 pcop = newpCodeOpLabel(NULL,-1);
1833 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1836 pcop->name = Safe_strdup(name);
1844 /*-----------------------------------------------------------------*/
1845 /*-----------------------------------------------------------------*/
1846 void pCodeConstString(char *name, char *value)
1850 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
1855 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
1859 sprintf(buffer,"; %s = %s",name,value);
1861 addpCode2pBlock(pb,newpCodeCharP(buffer));
1862 addpCode2pBlock(pb,newpCodeLabel(name,-1));
1865 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
1871 /*-----------------------------------------------------------------*/
1872 /*-----------------------------------------------------------------*/
1873 void pCodeReadCodeTable(void)
1877 fprintf(stderr, " %s\n",__FUNCTION__);
1879 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
1883 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
1884 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
1885 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
1886 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
1888 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
1889 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
1890 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
1891 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
1896 /*-----------------------------------------------------------------*/
1897 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1898 /*-----------------------------------------------------------------*/
1899 void addpCode2pBlock(pBlock *pb, pCode *pc)
1902 /* If this is the first pcode to be added to a block that
1903 * was initialized with a NULL pcode, then go ahead and
1904 * make this pcode the head and tail */
1905 pb->pcHead = pb->pcTail = pc;
1907 pb->pcTail->next = pc;
1908 pc->prev = pb->pcTail;
1915 /*-----------------------------------------------------------------*/
1916 /* addpBlock - place a pBlock into the pFile */
1917 /*-----------------------------------------------------------------*/
1918 void addpBlock(pBlock *pb)
1920 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
1923 /* First time called, we'll pass through here. */
1924 //_ALLOC(the_pFile,sizeof(pFile));
1925 the_pFile = Safe_calloc(1,sizeof(pFile));
1926 the_pFile->pbHead = the_pFile->pbTail = pb;
1927 the_pFile->functions = NULL;
1931 the_pFile->pbTail->next = pb;
1932 pb->prev = the_pFile->pbTail;
1934 the_pFile->pbTail = pb;
1937 /*-----------------------------------------------------------------*/
1938 /* printpCode - write the contents of a pCode to a file */
1939 /*-----------------------------------------------------------------*/
1940 void printpCode(FILE *of, pCode *pc)
1951 fprintf(of,"warning - unable to print pCode\n");
1954 /*-----------------------------------------------------------------*/
1955 /* printpBlock - write the contents of a pBlock to a file */
1956 /*-----------------------------------------------------------------*/
1957 void printpBlock(FILE *of, pBlock *pb)
1967 for(pc = pb->pcHead; pc; pc = pc->next)
1972 /*-----------------------------------------------------------------*/
1974 /* pCode processing */
1978 /*-----------------------------------------------------------------*/
1980 static void unlinkPC(pCode *pc)
1986 pc->prev->next = pc->next;
1988 pc->next->prev = pc->prev;
1990 pc->prev = pc->next = NULL;
1993 static void genericDestruct(pCode *pc)
1995 fprintf(stderr,"warning, calling default pCode destructor\n");
2004 /*-----------------------------------------------------------------*/
2005 /*-----------------------------------------------------------------*/
2006 void pBlockRegs(FILE *of, pBlock *pb)
2011 r = setFirstItem(pb->tregisters);
2013 r = setNextItem(pb->tregisters);
2018 static char *get_op( pCodeInstruction *pcc)
2021 static char buffer[50];
2025 if(pcc && pcc->pcop) {
2028 switch(pcc->pcop->type) {
2031 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2032 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2034 return PCOR(pcc->pcop)->r->name;
2037 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
2038 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2039 pBlockRegs(stderr,pcc->pc.pb);
2043 // return PCOR(pcc->pcop)->r)->name;
2046 size = sizeof(buffer);
2047 if( PCOI(pcc->pcop)->offset && PCOI(pcc->pcop)->offset<4) {
2048 SAFE_snprintf(&s,&size,"((%s >> %d)&0xff)",
2050 8 * PCOI(pcc->pcop)->offset );
2052 SAFE_snprintf(&s,&size,"LOW(%s)",pcc->pcop->name);
2058 if (pcc->pcop->name)
2059 return pcc->pcop->name;
2064 return "NO operand";
2067 /*-----------------------------------------------------------------*/
2068 /*-----------------------------------------------------------------*/
2069 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2072 fprintf(of,"pcodeopprint\n");
2075 char *pCode2str(char *str, int size, pCode *pc)
2083 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2085 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2087 if(PCI(pc)->isBitInst) {
2088 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2089 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2090 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2091 PCI(pc)->pcop->name ,
2092 PCI(pc)->pcop->name );
2094 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
2095 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2096 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2097 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2099 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
2100 //PCI(pc)->pcop->t.bit );
2103 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2104 if( PCI(pc)->num_ops == 2)
2105 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2107 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
2110 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
2112 if( PCI(pc)->num_ops == 2)
2113 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2121 /* assuming that comment ends with a \n */
2122 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2126 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2129 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2132 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2135 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2143 /*-----------------------------------------------------------------*/
2144 /* genericPrint - the contents of a pCode to a file */
2145 /*-----------------------------------------------------------------*/
2146 static void genericPrint(FILE *of, pCode *pc)
2154 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2158 // If the opcode has a label, print that first
2160 pBranch *pbl = PCI(pc)->label;
2161 while(pbl && pbl->pc) {
2162 if(pbl->pc->type == PC_LABEL)
2163 pCodePrintLabel(of, pbl->pc);
2172 pCode2str(str, 256, pc);
2174 fprintf(of,"%s",str);
2177 fprintf(of, "\t;key=%03x",pc->seq);
2179 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2183 pBranch *dpb = pc->to; // debug
2185 switch ( dpb->pc->type) {
2187 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2190 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2193 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2196 fprintf(of, "\t;flow");
2210 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2211 if(PCW(pc)->pci.label)
2212 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2214 if(PCW(pc)->operand) {
2215 fprintf(of,";\toperand ");
2216 pCodeOpPrint(of,PCW(pc)->operand );
2221 fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2226 fprintf(of,"unknown pCode type %d\n",pc->type);
2231 /*-----------------------------------------------------------------*/
2232 /* pCodePrintFunction - prints function begin/end */
2233 /*-----------------------------------------------------------------*/
2235 static void pCodePrintFunction(FILE *of, pCode *pc)
2241 if( ((pCodeFunction *)pc)->modname)
2242 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2244 if(PCF(pc)->fname) {
2245 pBranch *exits = PCF(pc)->to;
2247 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2250 exits = exits->next;
2253 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2256 if((PCF(pc)->from &&
2257 PCF(pc)->from->pc->type == PC_FUNCTION &&
2258 PCF(PCF(pc)->from->pc)->fname) )
2259 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2261 fprintf(of,"; exit point [can't find entry point]\n");
2264 /*-----------------------------------------------------------------*/
2265 /* pCodePrintLabel - prints label */
2266 /*-----------------------------------------------------------------*/
2268 static void pCodePrintLabel(FILE *of, pCode *pc)
2275 fprintf(of,"%s\n",PCL(pc)->label);
2276 else if (PCL(pc)->key >=0)
2277 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2279 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2282 /*-----------------------------------------------------------------*/
2283 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2284 /* remove it if it is found. */
2285 /*-----------------------------------------------------------------*/
2286 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2293 if(pcl->type == PC_OPCODE)
2294 b = PCI(pcl)->label;
2296 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2306 bprev->next = b->next; /* Not first pCode in chain */
2310 PCI(pcl)->label = b->next; /* First pCode in chain */
2313 return; /* A label can't occur more than once */
2330 bprev->next = b->next; /* Not first pCode in chain */
2334 pcl->label = b->next; /* First pCode in chain */
2337 return; /* A label can't occur more than once */
2345 /*-----------------------------------------------------------------*/
2346 /*-----------------------------------------------------------------*/
2347 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2363 /*-----------------------------------------------------------------*/
2364 /* pBranchLink - given two pcodes, this function will link them */
2365 /* together through their pBranches */
2366 /*-----------------------------------------------------------------*/
2367 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2371 // Declare a new branch object for the 'from' pCode.
2373 //_ALLOC(b,sizeof(pBranch));
2374 b = Safe_calloc(1,sizeof(pBranch));
2375 b->pc = PCODE(t); // The link to the 'to' pCode.
2378 f->to = pBranchAppend(f->to,b);
2380 // Now do the same for the 'to' pCode.
2382 //_ALLOC(b,sizeof(pBranch));
2383 b = Safe_calloc(1,sizeof(pBranch));
2387 t->from = pBranchAppend(t->from,b);
2392 /*-----------------------------------------------------------------*/
2393 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2395 /*-----------------------------------------------------------------*/
2396 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2409 /*-----------------------------------------------------------------*/
2410 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2411 /*-----------------------------------------------------------------*/
2412 static void pCodeUnlink(pCode *pc)
2417 if(!pc->prev || !pc->next) {
2418 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2422 /* first remove the pCode from the chain */
2423 pc->prev->next = pc->next;
2424 pc->next->prev = pc->prev;
2426 /* Now for the hard part... */
2428 /* Remove the branches */
2432 pc1 = pb1->pc; /* Get the pCode that branches to the
2433 * one we're unlinking */
2435 /* search for the link back to this pCode (the one we're
2437 if(pb2 = pBranchFind(pc1->to,pc)) {
2438 pb2->pc = pc->to->pc; // make the replacement
2440 /* if the pCode we're unlinking contains multiple 'to'
2441 * branches (e.g. this a skip instruction) then we need
2442 * to copy these extra branches to the chain. */
2444 pBranchAppend(pb2, pc->to->next);
2453 /*-----------------------------------------------------------------*/
2454 /*-----------------------------------------------------------------*/
2456 static void genericAnalyze(pCode *pc)
2466 // Go through the pCodes that are in pCode chain and link
2467 // them together through the pBranches. Note, the pCodes
2468 // are linked together as a contiguous stream like the
2469 // assembly source code lines. The linking here mimics this
2470 // except that comments are not linked in.
2472 pCode *npc = pc->next;
2474 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2475 pBranchLink(pc,npc);
2480 /* reached the end of the pcode chain without finding
2481 * an instruction we could link to. */
2485 fprintf(stderr,"analyze PC_FLOW\n");
2492 /*-----------------------------------------------------------------*/
2493 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2497 if(pc->type == PC_LABEL) {
2498 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2501 if(pc->type == PC_OPCODE) {
2502 pbr = PCI(pc)->label;
2504 if(pbr->pc->type == PC_LABEL) {
2505 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2515 /*-----------------------------------------------------------------*/
2516 /* findLabel - Search the pCode for a particular label */
2517 /*-----------------------------------------------------------------*/
2518 pCode * findLabel(pCodeOpLabel *pcop_label)
2526 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2527 for(pc = pb->pcHead; pc; pc = pc->next)
2528 if(compareLabel(pc,pcop_label))
2533 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2537 /*-----------------------------------------------------------------*/
2538 /* findNextpCode - given a pCode, find the next of type 'pct' */
2539 /* in the linked list */
2540 /*-----------------------------------------------------------------*/
2541 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2554 /*-----------------------------------------------------------------*/
2555 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2556 /* in the linked list */
2557 /*-----------------------------------------------------------------*/
2558 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2570 /*-----------------------------------------------------------------*/
2571 /* findNextInstruction - given a pCode, find the next instruction */
2572 /* in the linked list */
2573 /*-----------------------------------------------------------------*/
2574 pCode * findNextInstruction(pCode *pc)
2578 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2584 //fprintf(stderr,"Couldn't find instruction\n");
2588 /*-----------------------------------------------------------------*/
2589 /* findFunctionEnd - given a pCode find the end of the function */
2590 /* that contains it t */
2591 /*-----------------------------------------------------------------*/
2592 pCode * findFunctionEnd(pCode *pc)
2596 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2602 fprintf(stderr,"Couldn't find function end\n");
2607 /*-----------------------------------------------------------------*/
2608 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2609 /* instruction with which it is associated. */
2610 /*-----------------------------------------------------------------*/
2611 static void AnalyzeLabel(pCode *pc)
2620 static void AnalyzeGOTO(pCode *pc)
2623 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2627 static void AnalyzeSKIP(pCode *pc)
2630 pBranchLink(pc,findNextInstruction(pc->next));
2631 pBranchLink(pc,findNextInstruction(pc->next->next));
2635 static void AnalyzeRETURN(pCode *pc)
2638 // branch_link(pc,findFunctionEnd(pc->next));
2644 /*-----------------------------------------------------------------*/
2645 /*-----------------------------------------------------------------*/
2646 regs * getRegFromInstruction(pCode *pc)
2651 PCI(pc)->num_ops == 0 )
2654 switch(PCI(pc)->pcop->type) {
2657 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2661 fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2662 return PCOR(PCI(pc)->pcop)->r;
2665 fprintf(stderr, "getRegFromInstruction - immediate\n");
2666 return NULL; // PCOR(PCI(pc)->pcop)->r;
2669 return PCOR(PCI(pc)->pcop)->r;
2672 fprintf(stderr, "getRegFromInstruction - dir\n");
2673 //return NULL; PCOR(PCI(pc)->pcop)->r;
2674 return PCOR(PCI(pc)->pcop)->r;
2676 fprintf(stderr, "getRegFromInstruction - literal\n");
2680 fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2681 genericPrint(stderr, pc);
2689 /*-----------------------------------------------------------------*/
2690 /*-----------------------------------------------------------------*/
2692 void AnalyzepBlock(pBlock *pb)
2699 /* Find all of the registers used in this pBlock
2700 * by looking at each instruction and examining it's
2703 for(pc = pb->pcHead; pc; pc = pc->next) {
2705 /* Is this an instruction with operands? */
2706 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2708 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2710 /* Loop through all of the registers declared so far in
2711 this block and see if we find this one there */
2713 regs *r = setFirstItem(pb->tregisters);
2716 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2717 PCOR(PCI(pc)->pcop)->r = r;
2720 r = setNextItem(pb->tregisters);
2724 /* register wasn't found */
2725 r = Safe_calloc(1, sizeof(regs));
2726 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2727 addSet(&pb->tregisters, r);
2728 PCOR(PCI(pc)->pcop)->r = r;
2729 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2731 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2734 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2735 if(PCOR(PCI(pc)->pcop)->r) {
2736 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2737 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2739 if(PCI(pc)->pcop->name)
2740 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2742 fprintf(stderr,"ERROR: NULL register\n");
2751 /*-----------------------------------------------------------------*/
2753 /*-----------------------------------------------------------------*/
2754 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2756 void InsertpFlow(pCode *pc, pCode **pflow)
2758 PCFL(*pflow)->end = pc;
2760 if(!pc || !pc->next)
2763 *pflow = newpCodeFlow();
2764 pCodeInsertAfter(pc, *pflow);
2767 /*-----------------------------------------------------------------*/
2768 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
2769 /* the flow blocks. */
2771 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2772 * point the instruction flow changes.
2774 /*-----------------------------------------------------------------*/
2775 void BuildFlow(pBlock *pb)
2778 pCode *last_pci=NULL;
2785 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
2786 /* Insert a pCodeFlow object at the beginning of a pBlock */
2788 pflow = newpCodeFlow(); /* Create a new Flow object */
2789 pflow->next = pb->pcHead; /* Make the current head the next object */
2790 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
2791 pb->pcHead = pflow; /* Make the Flow object the head */
2794 for( pc = findNextInstruction(pb->pcHead);
2795 (pc=findNextInstruction(pc)) != NULL; ) {
2798 PCI(pc)->pcflow = PCFL(pflow);
2800 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
2802 /* The instruction immediately following this one
2803 * marks the beginning of a new flow segment */
2805 InsertpFlow(pc, &pflow);
2808 } else if (PCI_HAS_LABEL(pc)) {
2810 /* This instruction marks the beginning of a
2811 * new flow segment */
2815 InsertpFlow(pc->prev, &pflow);
2817 PCI(pc)->pcflow = PCFL(pflow);
2824 //fprintf (stderr,",end seq %d",GpcFlowSeq);
2825 PCFL(pflow)->end = pb->pcTail;
2828 /*-----------------------------------------------------------------*/
2829 /*-----------------------------------------------------------------*/
2830 void dumpCond(int cond)
2833 static char *pcc_str[] = {
2847 int ncond = sizeof(pcc_str) / sizeof(char *);
2850 fprintf(stderr, "0x%04X\n",cond);
2852 for(i=0,j=1; i<ncond; i++, j<<=1)
2854 fprintf(stderr, " %s\n",pcc_str[i]);
2858 /*-----------------------------------------------------------------*/
2859 /*-----------------------------------------------------------------*/
2860 void FillFlow(pCodeFlow *pcflow)
2869 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
2871 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
2873 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
2882 int inCond = PCI(pc)->inCond;
2883 int outCond = PCI(pc)->outCond;
2885 if( (reg = getRegFromInstruction(pc)) != NULL) {
2886 if(isSTATUS_REG(reg)) {
2888 //fprintf(stderr, " FillFlow - Status register\n");
2890 /* Check to see if the register banks are changing */
2891 if(PCI(pc)->isModReg) {
2893 pCodeOp *pcop = PCI(pc)->pcop;
2894 switch(PCI(pc)->op) {
2896 if(PCORB(pcop)->bit == PIC_RP0_BIT)
2897 fprintf(stderr, " FillFlow - Set RP0\n");
2898 //outCond |= PCC_REG_BANK1;
2899 if(PCORB(pcop)->bit == PIC_RP1_BIT)
2900 fprintf(stderr, " FillFlow - Set RP1\n");
2901 //outCond |= PCC_REG_BANK3;
2905 if(PCORB(pcop)->bit == PIC_RP0_BIT)
2906 fprintf(stderr, " FillFlow - Clr RP0\n");
2907 //outCond |= PCC_REG_BANK1;
2908 if(PCORB(pcop)->bit == PIC_RP1_BIT)
2909 fprintf(stderr, " FillFlow - Clr RP1\n");
2910 //outCond |= PCC_REG_BANK3;
2914 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
2915 genericPrint(stderr, pc);
2920 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
2924 pcflow->inCond |= (inCond & ~pcflow->outCond);
2925 pcflow->outCond |= outCond;
2930 pc = findNextpCode(pc->next, PC_OPCODE);
2931 } while (pc && (pc != pcflow->end));
2935 fprintf(stderr, " FillFlow - Bad end of flow\n");
2938 fprintf(stderr, " FillFlow inCond: ");
2939 dumpCond(pcflow->inCond);
2940 fprintf(stderr, " FillFlow outCond: ");
2941 dumpCond(pcflow->outCond);
2944 /*-----------------------------------------------------------------*/
2945 /*-----------------------------------------------------------------*/
2946 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
2949 if(!from || !to || !to->pcflow || !from->pcflow)
2952 addSet(&(from->pcflow->to), to->pcflow);
2953 addSet(&(to->pcflow->from), from->pcflow);
2957 /*-----------------------------------------------------------------*/
2958 /*-----------------------------------------------------------------*/
2959 void LinkFlow(pBlock *pb)
2966 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
2967 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
2968 pcflow = pcflow->next) {
2971 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
2973 //FillFlow(PCFL(pcflow));
2975 pc = PCFL(pcflow)->end;
2977 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
2978 if(isPCI_SKIP(pc)) {
2979 //fprintf(stderr, "ends with skip\n");
2980 pct=findNextInstruction(pc->next);
2981 LinkFlow_pCode(PCI(pc),PCI(pct));
2982 pct=findNextInstruction(pct->next);
2983 LinkFlow_pCode(PCI(pc),PCI(pct));
2987 if(isPCI_BRANCH(pc)) {
2988 //fprintf(stderr, "ends with branch\n");
2994 fprintf(stderr, "has an unrecognized ending:\n");
2995 pc->print(stderr,pc);
2998 fprintf(stderr, "has no end pcode\n");
3003 /*-----------------------------------------------------------------*/
3004 /*-----------------------------------------------------------------*/
3005 int OptimizepBlock(pBlock *pb)
3010 if(!pb || !peepOptimizing)
3013 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3014 for(pc = pb->pcHead; pc; pc = pc->next)
3015 matches += pCodePeepMatchRule(pc);
3017 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3022 /*-----------------------------------------------------------------*/
3023 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3024 /*-----------------------------------------------------------------*/
3025 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3029 for(pc = pcs; pc; pc = pc->next) {
3031 if((pc->type == PC_OPCODE) &&
3033 (PCI(pc)->pcop->type == PO_LABEL) &&
3034 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3042 /*-----------------------------------------------------------------*/
3043 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3044 /* pCode chain if they're not used. */
3045 /*-----------------------------------------------------------------*/
3046 void pBlockRemoveUnusedLabels(pBlock *pb)
3048 pCode *pc; pCodeLabel *pcl;
3053 for(pc = pb->pcHead; pc; pc = pc->next) {
3055 if(pc->type == PC_LABEL)
3057 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3058 pcl = PCL(PCI(pc)->label->pc);
3061 /* This pCode is a label, so search the pBlock to see if anyone
3064 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3065 /* Couldn't find an instruction that refers to this label
3066 * So, unlink the pCode label from it's pCode chain
3067 * and destroy the label */
3069 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3071 if(pc->type == PC_LABEL) {
3073 pCodeLabelDestruct(pc);
3075 unlinkpCodeFromBranch(pc, PCODE(pcl));
3076 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3087 /*-----------------------------------------------------------------*/
3088 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3089 /* chain and put them into pBranches that are */
3090 /* associated with the appropriate pCode */
3092 /*-----------------------------------------------------------------*/
3093 void pBlockMergeLabels(pBlock *pb)
3096 pCode *pc, *pcnext=NULL;
3101 /* First, Try to remove any unused labels */
3102 //pBlockRemoveUnusedLabels(pb);
3104 /* Now loop through the pBlock and merge the labels with the opcodes */
3106 for(pc = pb->pcHead; pc; pc = pc->next) {
3108 if(pc->type == PC_LABEL) {
3109 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3110 if( !(pcnext = findNextInstruction(pc)) )
3111 return; // Couldn't find an instruction associated with this label
3113 // Unlink the pCode label from it's pCode chain
3116 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3117 // And link it into the instruction's pBranch labels. (Note, since
3118 // it's possible to have multiple labels associated with one instruction
3119 // we must provide a means to accomodate the additional labels. Thus
3120 // the labels are placed into the singly-linked list "label" as
3121 // opposed to being a single member of the pCodeInstruction.)
3123 //_ALLOC(pbr,sizeof(pBranch));
3124 pbr = Safe_calloc(1,sizeof(pBranch));
3128 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3136 pBlockRemoveUnusedLabels(pb);
3140 /*-----------------------------------------------------------------*/
3141 /*-----------------------------------------------------------------*/
3142 void OptimizepCode(char dbName)
3144 #define MAX_PASSES 4
3153 DFPRINTF((stderr," Optimizing pCode\n"));
3156 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3157 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3158 matches += OptimizepBlock(pb);
3161 while(matches && ++passes < MAX_PASSES);
3165 /*-----------------------------------------------------------------*/
3166 /* popCopy - copy a pcode operator */
3167 /*-----------------------------------------------------------------*/
3168 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3172 pcop = newpCodeOpBit(pc->name, bitval, 0);
3174 if( !( (pcop->type == PO_LABEL) ||
3175 (pcop->type == PO_LITERAL) ||
3176 (pcop->type == PO_STR) ))
3177 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3185 /*-----------------------------------------------------------------*/
3186 /*-----------------------------------------------------------------*/
3187 int InstructionRegBank(pCode *pc)
3191 if( (reg = getRegFromInstruction(pc)) == NULL)
3194 return REG_BANK(reg);
3199 /*-----------------------------------------------------------------*/
3200 /*-----------------------------------------------------------------*/
3201 void FixRegisterBanking(pBlock *pb)
3213 pc = findNextpCode(pb->pcHead, PC_FLOW);
3216 /* loop through all of the flow blocks with in one pblock */
3218 // fprintf(stderr,"Register banking\n");
3221 /* at this point, pc should point to a PC_FLOW object */
3224 /* for each flow block, determine the register banking
3229 genericPrint(stderr, pc);
3231 reg = getRegFromInstruction(pc);
3234 fprintf(stderr, " %s ",reg->name);
3235 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3239 if(reg && REG_BANK(reg)!=cur_bank) {
3240 /* Examine the instruction before this one to make sure it is
3241 * not a skip type instruction */
3242 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3243 if(pcprev && !isPCI_SKIP(pcprev)) {
3244 int b = cur_bank ^ REG_BANK(reg);
3246 //fprintf(stderr, "Cool! can switch banks\n");
3247 cur_bank = REG_BANK(reg);
3249 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3250 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3251 pCodeInsertAfter(pc->prev, new_pc);
3252 if(PCI(pc)->label) {
3253 PCI(new_pc)->label = PCI(pc)->label;
3254 PCI(pc)->label = NULL;
3257 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3258 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3259 pCodeInsertAfter(pc, new_pc);
3265 fprintf(stderr, "Bummer can't switch banks\n");
3271 } while(pc && !(isPCFL(pc)));
3273 if(pcprev && cur_bank) {
3274 /* Brute force - make sure that we point to bank 0 at the
3275 * end of each flow block */
3276 new_pc = newpCode(POC_BCF,
3277 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3278 pCodeInsertAfter(pcprev, new_pc);
3286 void pBlockDestruct(pBlock *pb)
3297 /*-----------------------------------------------------------------*/
3298 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3299 /* name dbName and combine them */
3300 /* into one block */
3301 /*-----------------------------------------------------------------*/
3302 void mergepBlocks(char dbName)
3305 pBlock *pb, *pbmerged = NULL,*pbn;
3307 pb = the_pFile->pbHead;
3309 //fprintf(stderr," merging blocks named %c\n",dbName);
3313 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3314 if( getpBlock_dbName(pb) == dbName) {
3316 //fprintf(stderr," merged block %c\n",dbName);
3321 addpCode2pBlock(pbmerged, pb->pcHead);
3322 /* addpCode2pBlock doesn't handle the tail: */
3323 pbmerged->pcTail = pb->pcTail;
3325 pb->prev->next = pbn;
3327 pbn->prev = pb->prev;
3332 //printpBlock(stderr, pbmerged);
3339 /*-----------------------------------------------------------------*/
3340 /* AnalyzeBanking - Called after the memory addresses have been */
3341 /* assigned to the registers. */
3343 /*-----------------------------------------------------------------*/
3344 void AnalyzeBanking(void)
3353 /* Phase 2 - Flow Analysis
3355 * In this phase, the pCode is partition into pCodeFlow
3356 * blocks. The flow blocks mark the points where a continuous
3357 * stream of instructions changes flow (e.g. because of
3358 * a call or goto or whatever).
3361 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3364 /* Phase 2 - Flow Analysis - linking flow blocks
3366 * In this phase, the individual flow blocks are examined
3367 * to determine their order of excution.
3370 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3373 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3374 FixRegisterBanking(pb);
3377 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3379 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3380 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3381 pcflow = pcflow->next) {
3383 FillFlow(PCFL(pcflow));
3390 /*-----------------------------------------------------------------*/
3391 /* buildCallTree - look at the flow and extract all of the calls */
3393 /*-----------------------------------------------------------------*/
3394 set *register_usage(pBlock *pb);
3396 void buildCallTree(void )
3407 /* Now build the call tree.
3408 First we examine all of the pCodes for functions.
3409 Keep in mind that the function boundaries coincide
3410 with pBlock boundaries.
3412 The algorithm goes something like this:
3413 We have two nested loops. The outer loop iterates
3414 through all of the pBlocks/functions. The inner
3415 loop iterates through all of the pCodes for
3416 a given pBlock. When we begin iterating through
3417 a pBlock, the variable pc_fstart, pCode of the start
3418 of a function, is cleared. We then search for pCodes
3419 of type PC_FUNCTION. When one is encountered, we
3420 initialize pc_fstart to this and at the same time
3421 associate a new pBranch object that signifies a
3422 branch entry. If a return is found, then this signifies
3423 a function exit point. We'll link the pCodes of these
3424 returns to the matching pc_fstart.
3426 When we're done, a doubly linked list of pBranches
3427 will exist. The head of this list is stored in
3428 `the_pFile', which is the meta structure for all
3429 of the pCode. Look at the printCallTree function
3430 on how the pBranches are linked together.
3433 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3434 pCode *pc_fstart=NULL;
3435 for(pc = pb->pcHead; pc; pc = pc->next) {
3436 if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
3437 if (PCF(pc)->fname) {
3439 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3440 fprintf(stderr," found main \n");
3441 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3445 //_ALLOC(pbr,sizeof(pBranch));
3446 pbr = Safe_calloc(1,sizeof(pBranch));
3447 pbr->pc = pc_fstart = pc;
3450 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3452 // Here's a better way of doing the same:
3453 addSet(&pb->function_entries, pc);
3456 // Found an exit point in a function, e.g. return
3457 // (Note, there may be more than one return per function)
3459 pBranchLink(PCF(pc_fstart), PCF(pc));
3461 addSet(&pb->function_exits, pc);
3463 } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3464 addSet(&pb->function_calls,pc);
3469 /* Re-allocate the registers so that there are no collisions
3470 * between local variables when one function call another */
3472 pic14_deallocateAllRegs();
3474 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3481 /*-----------------------------------------------------------------*/
3482 /* AnalyzepCode - parse the pCode that has been generated and form */
3483 /* all of the logical connections. */
3485 /* Essentially what's done here is that the pCode flow is */
3487 /*-----------------------------------------------------------------*/
3489 void AnalyzepCode(char dbName)
3500 /* Phase 1 - Register allocation and peep hole optimization
3502 * The first part of the analysis is to determine the registers
3503 * that are used in the pCode. Once that is done, the peep rules
3504 * are applied to the code. We continue to loop until no more
3505 * peep rule optimizations are found (or until we exceed the
3506 * MAX_PASSES threshold).
3508 * When done, the required registers will be determined.
3514 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3516 /* First, merge the labels with the instructions */
3517 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3518 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3520 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3521 //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3522 pBlockMergeLabels(pb);
3529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3530 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3531 changes += OptimizepBlock(pb);
3534 } while(changes && (i++ < MAX_PASSES));
3539 /*-----------------------------------------------------------------*/
3540 /* ispCodeFunction - returns true if *pc is the pCode of a */
3542 /*-----------------------------------------------------------------*/
3543 bool ispCodeFunction(pCode *pc)
3546 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3552 /*-----------------------------------------------------------------*/
3553 /* findFunction - Search for a function by name (given the name) */
3554 /* in the set of all functions that are in a pBlock */
3555 /* (note - I expect this to change because I'm planning to limit */
3556 /* pBlock's to just one function declaration */
3557 /*-----------------------------------------------------------------*/
3558 pCode *findFunction(char *fname)
3565 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3567 pc = setFirstItem(pb->function_entries);
3570 if((pc->type == PC_FUNCTION) &&
3572 (strcmp(fname, PCF(pc)->fname)==0))
3575 pc = setNextItem(pb->function_entries);
3583 void MarkUsedRegisters(set *regset)
3588 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3589 r2 = pic14_regWithIdx(r1->rIdx);
3595 void pBlockStats(FILE *of, pBlock *pb)
3601 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3603 // for now just print the first element of each set
3604 pc = setFirstItem(pb->function_entries);
3606 fprintf(of,";entry: ");
3609 pc = setFirstItem(pb->function_exits);
3611 fprintf(of,";has an exit\n");
3615 pc = setFirstItem(pb->function_calls);
3617 fprintf(of,";functions called:\n");
3620 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3621 fprintf(of,"; %s\n",get_op(PCI(pc)));
3623 pc = setNextItem(pb->function_calls);
3627 r = setFirstItem(pb->tregisters);
3629 int n = elementsInSet(pb->tregisters);
3631 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3634 fprintf(of,"; %s\n",r->name);
3635 r = setNextItem(pb->tregisters);
3640 /*-----------------------------------------------------------------*/
3641 /*-----------------------------------------------------------------*/
3642 static void sequencepCode(void)
3648 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3650 pb->seq = GpCodeSequenceNumber+1;
3652 for( pc = pb->pcHead; pc; pc = pc->next)
3653 pc->seq = ++GpCodeSequenceNumber;
3658 /*-----------------------------------------------------------------*/
3659 /*-----------------------------------------------------------------*/
3660 set *register_usage(pBlock *pb)
3663 set *registers=NULL;
3664 set *registersInCallPath = NULL;
3666 /* check recursion */
3668 pc = setFirstItem(pb->function_entries);
3675 if(pc->type != PC_FUNCTION)
3676 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3678 pc = setFirstItem(pb->function_calls);
3679 for( ; pc; pc = setNextItem(pb->function_calls)) {
3681 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3682 char *dest = get_op(PCI(pc));
3684 pcn = findFunction(dest);
3686 registersInCallPath = register_usage(pcn->pb);
3688 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3693 pBlockStats(stderr,pb); // debug
3696 // Mark the registers in this block as used.
3698 MarkUsedRegisters(pb->tregisters);
3699 if(registersInCallPath) {
3700 /* registers were used in the functions this pBlock has called */
3701 /* so now, we need to see if these collide with the ones we are */
3704 regs *r1,*r2, *newreg;
3706 DFPRINTF((stderr,"comparing registers\n"));
3708 r1 = setFirstItem(registersInCallPath);
3711 r2 = setFirstItem(pb->tregisters);
3713 while(r2 && (r1->type != REG_STK)) {
3715 if(r2->rIdx == r1->rIdx) {
3716 newreg = pic14_findFreeReg(REG_GPR);
3720 DFPRINTF((stderr,"Bummer, no more registers.\n"));
3724 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3725 r1->rIdx, newreg->rIdx));
3726 r2->rIdx = newreg->rIdx;
3727 //if(r2->name) free(r2->name);
3729 r2->name = Safe_strdup(newreg->name);
3733 newreg->wasUsed = 1;
3735 r2 = setNextItem(pb->tregisters);
3738 r1 = setNextItem(registersInCallPath);
3741 /* Collisions have been resolved. Now free the registers in the call path */
3742 r1 = setFirstItem(registersInCallPath);
3744 if(r1->type != REG_STK) {
3745 newreg = pic14_regWithIdx(r1->rIdx);
3748 r1 = setNextItem(registersInCallPath);
3752 // MarkUsedRegisters(pb->registers);
3754 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3757 DFPRINTF((stderr,"returning regs\n"));
3759 DFPRINTF((stderr,"not returning regs\n"));
3761 DFPRINTF((stderr,"pBlock after register optim.\n"));
3762 pBlockStats(stderr,pb); // debug
3768 /*-----------------------------------------------------------------*/
3769 /* printCallTree - writes the call tree to a file */
3771 /*-----------------------------------------------------------------*/
3772 void pct2(FILE *of,pBlock *pb,int indent)
3776 // set *registersInCallPath = NULL;
3779 return;// registers;
3782 return; // registers; //recursion ?
3784 pc = setFirstItem(pb->function_entries);
3791 for(i=0;i<indent;i++) // Indentation
3794 if(pc->type == PC_FUNCTION)
3795 fprintf(of,"%s\n",PCF(pc)->fname);
3800 pc = setFirstItem(pb->function_calls);
3801 for( ; pc; pc = setNextItem(pb->function_calls)) {
3803 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3804 char *dest = get_op(PCI(pc));
3806 pcn = findFunction(dest);
3808 pct2(of,pcn->pb,indent+1);
3810 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3818 fprintf(stderr,"pBlock before register optim.\n");
3819 pBlockStats(stderr,pb); // debug
3821 if(registersInCallPath) {
3822 /* registers were used in the functions this pBlock has called */
3823 /* so now, we need to see if these collide with the ones we are using here */
3825 regs *r1,*r2, *newreg;
3827 fprintf(stderr,"comparing registers\n");
3829 r1 = setFirstItem(registersInCallPath);
3832 r2 = setFirstItem(pb->registers);
3836 if(r2->rIdx == r1->rIdx) {
3837 newreg = pic14_findFreeReg();
3841 fprintf(stderr,"Bummer, no more registers.\n");
3845 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
3846 r1->rIdx, newreg->rIdx);
3847 r2->rIdx = newreg->rIdx;
3848 //if(r2->name) free(r2->name);
3850 r2->name = Safe_strdup(newreg->name);
3854 newreg->wasUsed = 1;
3856 r2 = setNextItem(pb->registers);
3859 r1 = setNextItem(registersInCallPath);
3862 /* Collisions have been resolved. Now free the registers in the call path */
3863 r1 = setFirstItem(registersInCallPath);
3865 newreg = pic14_regWithIdx(r1->rIdx);
3867 r1 = setNextItem(registersInCallPath);
3871 MarkUsedRegisters(pb->registers);
3873 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
3876 fprintf(stderr,"returning regs\n");
3878 fprintf(stderr,"not returning regs\n");
3880 fprintf(stderr,"pBlock after register optim.\n");
3881 pBlockStats(stderr,pb); // debug
3889 /*-----------------------------------------------------------------*/
3890 /* printCallTree - writes the call tree to a file */
3892 /*-----------------------------------------------------------------*/
3894 void printCallTree(FILE *of)
3906 fprintf(of, "\npBlock statistics\n");
3907 for(pb = the_pFile->pbHead; pb; pb = pb->next )
3912 fprintf(of,"Call Tree\n");
3913 pbr = the_pFile->functions;
3917 if(!ispCodeFunction(pc))
3918 fprintf(of,"bug in call tree");
3921 fprintf(of,"Function: %s\n", PCF(pc)->fname);
3923 while(pc->next && !ispCodeFunction(pc->next)) {
3925 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
3926 fprintf(of,"\t%s\n",get_op(PCI(pc)));
3934 /* Re-allocate the registers so that there are no collisions
3935 * between local variables when one function call another */
3937 pic14_deallocateAllRegs();
3939 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3945 fprintf(of,"\n**************\n\na better call tree\n");
3946 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3951 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3952 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));