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 int peepOptimizing = 1;
74 static int GpCodeSequenceNumber = 1;
75 static int GpcFlowSeq = 1;
77 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE))
78 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch)
79 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip)
80 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst)
81 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW))
82 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION))
83 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL))
84 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
86 /****************************************************************/
87 /* Forward declarations */
88 /****************************************************************/
90 static void unlinkPC(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);
106 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
107 int pCodePeepMatchRule(pCode *pc);
108 void pBlockStats(FILE *of, pBlock *pb);
109 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
111 pCodeInstruction pciADDWF = {
112 {PC_OPCODE, NULL, NULL, 0, NULL,
124 1,0, // dest, bit instruction
127 (PCC_W | PCC_REGISTER), // inCond
128 (PCC_REGISTER | PCC_Z) // outCond
131 pCodeInstruction pciADDFW = {
132 {PC_OPCODE, NULL, NULL, 0, NULL,
144 0,0, // dest, bit instruction
147 (PCC_W | PCC_REGISTER), // inCond
148 (PCC_W | PCC_Z) // outCond
151 pCodeInstruction pciADDLW = {
152 {PC_OPCODE, NULL, NULL, 0, NULL,
164 0,0, // dest, bit instruction
168 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
171 pCodeInstruction pciANDLW = {
172 {PC_OPCODE, NULL, NULL, 0, NULL,
184 0,0, // dest, bit instruction
188 (PCC_W | PCC_Z) // outCond
191 pCodeInstruction pciANDWF = {
192 {PC_OPCODE, NULL, NULL, 0, NULL,
204 1,0, // dest, bit instruction
207 (PCC_W | PCC_REGISTER), // inCond
208 (PCC_REGISTER | PCC_Z) // outCond
211 pCodeInstruction pciANDFW = {
212 {PC_OPCODE, NULL, NULL, 0, NULL,
224 0,0, // dest, bit instruction
227 (PCC_W | PCC_REGISTER), // inCond
228 (PCC_W | PCC_Z) // outCond
231 pCodeInstruction pciBCF = {
232 {PC_OPCODE, NULL, NULL, 0, NULL,
244 1,1, // dest, bit instruction
247 PCC_REGISTER, // inCond
248 PCC_REGISTER // outCond
251 pCodeInstruction pciBSF = {
252 {PC_OPCODE, NULL, NULL, 0, NULL,
264 1,1, // dest, bit instruction
267 PCC_REGISTER, // inCond
268 PCC_REGISTER // outCond
271 pCodeInstruction pciBTFSC = {
272 {PC_OPCODE, NULL, NULL, 0, NULL,
284 0,1, // dest, bit instruction
287 PCC_REGISTER, // inCond
291 pCodeInstruction pciBTFSS = {
292 {PC_OPCODE, NULL, NULL, 0, NULL,
304 0,1, // dest, bit instruction
307 PCC_REGISTER, // inCond
311 pCodeInstruction pciCALL = {
312 {PC_OPCODE, NULL, NULL, 0, NULL,
324 0,0, // dest, bit instruction
331 pCodeInstruction pciCOMF = {
332 {PC_OPCODE, NULL, NULL, 0, NULL,
344 1,0, // dest, bit instruction
347 PCC_REGISTER, // inCond
348 PCC_REGISTER // outCond
351 pCodeInstruction pciCOMFW = {
352 {PC_OPCODE, NULL, NULL, 0, NULL,
364 0,0, // dest, bit instruction
367 PCC_REGISTER, // inCond
371 pCodeInstruction pciCLRF = {
372 {PC_OPCODE, NULL, NULL, 0, NULL,
384 0,0, // dest, bit instruction
387 PCC_REGISTER, // inCond
388 PCC_REGISTER // outCond
391 pCodeInstruction pciCLRW = {
392 {PC_OPCODE, NULL, NULL, 0, NULL,
404 0,0, // dest, bit instruction
411 pCodeInstruction pciDECF = {
412 {PC_OPCODE, NULL, NULL, 0, NULL,
424 1,0, // dest, bit instruction
427 PCC_REGISTER, // inCond
428 PCC_REGISTER // outCond
431 pCodeInstruction pciDECFW = {
432 {PC_OPCODE, NULL, NULL, 0, NULL,
444 0,0, // dest, bit instruction
447 PCC_REGISTER, // inCond
451 pCodeInstruction pciDECFSZ = {
452 {PC_OPCODE, NULL, NULL, 0, NULL,
464 1,0, // dest, bit instruction
467 PCC_REGISTER, // inCond
468 PCC_REGISTER // outCond
471 pCodeInstruction pciDECFSZW = {
472 {PC_OPCODE, NULL, NULL, 0, NULL,
484 0,0, // dest, bit instruction
487 PCC_REGISTER, // inCond
491 pCodeInstruction pciGOTO = {
492 {PC_OPCODE, NULL, NULL, 0, NULL,
504 0,0, // dest, bit instruction
511 pCodeInstruction pciINCF = {
512 {PC_OPCODE, NULL, NULL, 0, NULL,
524 1,0, // dest, bit instruction
527 PCC_REGISTER, // inCond
528 PCC_REGISTER // outCond
531 pCodeInstruction pciINCFW = {
532 {PC_OPCODE, NULL, NULL, 0, NULL,
544 0,0, // dest, bit instruction
547 PCC_REGISTER, // inCond
551 pCodeInstruction pciINCFSZ = {
552 {PC_OPCODE, NULL, NULL, 0, NULL,
564 1,0, // dest, bit instruction
567 PCC_REGISTER, // inCond
568 PCC_REGISTER // outCond
571 pCodeInstruction pciINCFSZW = {
572 {PC_OPCODE, NULL, NULL, 0, NULL,
584 0,0, // dest, bit instruction
587 PCC_REGISTER, // inCond
591 pCodeInstruction pciIORWF = {
592 {PC_OPCODE, NULL, NULL, 0, NULL,
604 1,0, // dest, bit instruction
607 (PCC_W | PCC_REGISTER), // inCond
608 (PCC_REGISTER | PCC_Z) // outCond
611 pCodeInstruction pciIORFW = {
612 {PC_OPCODE, NULL, NULL, 0, NULL,
624 0,0, // dest, bit instruction
627 (PCC_W | PCC_REGISTER), // inCond
628 (PCC_W | PCC_Z) // outCond
631 pCodeInstruction pciIORLW = {
632 {PC_OPCODE, NULL, NULL, 0, NULL,
644 0,0, // dest, bit instruction
648 (PCC_W | PCC_Z) // outCond
651 pCodeInstruction pciMOVF = {
652 {PC_OPCODE, NULL, NULL, 0, NULL,
664 1,0, // dest, bit instruction
667 PCC_REGISTER, // inCond
671 pCodeInstruction pciMOVFW = {
672 {PC_OPCODE, NULL, NULL, 0, NULL,
684 0,0, // dest, bit instruction
687 PCC_REGISTER, // inCond
688 (PCC_W | PCC_Z) // outCond
691 pCodeInstruction pciMOVWF = {
692 {PC_OPCODE, NULL, NULL, 0, NULL,
704 0,0, // dest, bit instruction
708 PCC_REGISTER // outCond
711 pCodeInstruction pciMOVLW = {
712 {PC_OPCODE, NULL, NULL, 0, NULL,
724 0,0, // dest, bit instruction
731 pCodeInstruction pciNOP = {
732 {PC_OPCODE, NULL, NULL, 0, NULL,
743 0,0, // dest, bit instruction
750 pCodeInstruction pciRETFIE = {
751 {PC_OPCODE, NULL, NULL, 0, NULL,
763 0,0, // dest, bit instruction
767 PCC_NONE // outCond (not true... affects the GIE bit too)
770 pCodeInstruction pciRETLW = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
783 0,0, // dest, bit instruction
790 pCodeInstruction pciRETURN = {
791 {PC_OPCODE, NULL, NULL, 0, NULL,
803 0,0, // dest, bit instruction
810 pCodeInstruction pciRLF = {
811 {PC_OPCODE, NULL, NULL, 0, NULL,
823 1,0, // dest, bit instruction
826 (PCC_C | PCC_REGISTER), // inCond
827 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
830 pCodeInstruction pciRLFW = {
831 {PC_OPCODE, NULL, NULL, 0, NULL,
843 0,0, // dest, bit instruction
846 (PCC_C | PCC_REGISTER), // inCond
847 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
850 pCodeInstruction pciRRF = {
851 {PC_OPCODE, NULL, NULL, 0, NULL,
863 1,0, // dest, bit instruction
866 (PCC_C | PCC_REGISTER), // inCond
867 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
870 pCodeInstruction pciRRFW = {
871 {PC_OPCODE, NULL, NULL, 0, NULL,
883 0,0, // dest, bit instruction
886 (PCC_C | PCC_REGISTER), // inCond
887 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
890 pCodeInstruction pciSUBWF = {
891 {PC_OPCODE, NULL, NULL, 0, NULL,
903 1,0, // dest, bit instruction
906 (PCC_W | PCC_REGISTER), // inCond
907 (PCC_REGISTER | PCC_Z) // outCond
910 pCodeInstruction pciSUBFW = {
911 {PC_OPCODE, NULL, NULL, 0, NULL,
923 0,0, // dest, bit instruction
926 (PCC_W | PCC_REGISTER), // inCond
927 (PCC_W | PCC_Z) // outCond
930 pCodeInstruction pciSUBLW = {
931 {PC_OPCODE, NULL, NULL, 0, NULL,
943 0,0, // dest, bit instruction
947 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
950 pCodeInstruction pciSWAPF = {
951 {PC_OPCODE, NULL, NULL, 0, NULL,
963 1,0, // dest, bit instruction
966 (PCC_REGISTER), // inCond
967 (PCC_REGISTER) // outCond
970 pCodeInstruction pciSWAPFW = {
971 {PC_OPCODE, NULL, NULL, 0, NULL,
983 0,0, // dest, bit instruction
986 (PCC_REGISTER), // inCond
990 pCodeInstruction pciTRIS = {
991 {PC_OPCODE, NULL, NULL, 0, NULL,
1003 0,0, // dest, bit instruction
1004 0,0, // branch, skip
1007 PCC_REGISTER // outCond
1010 pCodeInstruction pciXORWF = {
1011 {PC_OPCODE, NULL, NULL, 0, NULL,
1017 NULL, // from branch
1023 1,0, // dest, bit instruction
1024 0,0, // branch, skip
1026 (PCC_W | PCC_REGISTER), // inCond
1027 (PCC_REGISTER | PCC_Z) // outCond
1030 pCodeInstruction pciXORFW = {
1031 {PC_OPCODE, NULL, NULL, 0, NULL,
1037 NULL, // from branch
1043 0,0, // dest, bit instruction
1044 0,0, // branch, skip
1046 (PCC_W | PCC_REGISTER), // inCond
1047 (PCC_W | PCC_Z) // outCond
1050 pCodeInstruction pciXORLW = {
1051 {PC_OPCODE, NULL, NULL, 0, NULL,
1057 NULL, // from branch
1063 0,0, // dest, bit instruction
1064 0,0, // branch, skip
1067 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1071 #define MAX_PIC14MNEMONICS 100
1072 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1074 /* This definition needs to be part of configure.in */
1075 // #define USE_VSNPRINTF
1077 #ifdef USE_VSNPRINTF
1078 // Alas, vsnprintf is not ANSI standard, and does not exist
1079 // on Solaris (and probably other non-Gnu flavored Unixes).
1081 /*-----------------------------------------------------------------*/
1082 /* SAFE_snprintf - like snprintf except the string pointer is */
1083 /* after the string has been printed to. This is */
1084 /* useful for printing to string as though if it */
1085 /* were a stream. */
1086 /*-----------------------------------------------------------------*/
1087 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1095 va_start(val, format);
1097 vsnprintf(*str, *size, format, val);
1103 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1111 #else // USE_VSNPRINTF
1113 // This version is *not* safe, despite the name.
1115 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1119 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1124 va_start(val, format);
1126 vsprintf(buffer, format, val);
1129 len = strlen(buffer);
1131 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1134 strcpy(*str, buffer);
1140 #endif // USE_VSNPRINTF
1143 extern void initStack(int base_address, int size);
1144 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1145 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1146 extern void init_pic(char *);
1148 void pCodeInitRegisters(void)
1152 init_pic(port->processor);
1154 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1155 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1156 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1157 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1158 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1159 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1161 pc_status.rIdx = IDX_STATUS;
1162 pc_fsr.rIdx = IDX_FSR;
1163 pc_indf.rIdx = IDX_INDF;
1164 pc_intcon.rIdx = IDX_INTCON;
1165 pc_pcl.rIdx = IDX_PCL;
1166 pc_pclath.rIdx = IDX_PCLATH;
1168 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1169 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1170 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1172 pc_kzero.rIdx = IDX_KZ;
1173 pc_wsave.rIdx = IDX_WSAVE;
1174 pc_ssave.rIdx = IDX_SSAVE;
1178 /*-----------------------------------------------------------------*/
1179 /* mnem2key - convert a pic mnemonic into a hash key */
1180 /* (BTW - this spreads the mnemonics quite well) */
1182 /*-----------------------------------------------------------------*/
1184 int mnem2key(char const *mnem)
1193 key += toupper(*mnem++) +1;
1197 return (key & 0x1f);
1201 void pic14initMnemonics(void)
1206 pCodeInstruction *pci;
1208 if(mnemonics_initialized)
1211 //FIXME - probably should NULL out the array before making the assignments
1212 //since we check the array contents below this initialization.
1214 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1215 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1216 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1217 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1218 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1219 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1220 pic14Mnemonics[POC_BCF] = &pciBCF;
1221 pic14Mnemonics[POC_BSF] = &pciBSF;
1222 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1223 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1224 pic14Mnemonics[POC_CALL] = &pciCALL;
1225 pic14Mnemonics[POC_COMF] = &pciCOMF;
1226 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1227 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1228 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1229 pic14Mnemonics[POC_DECF] = &pciDECF;
1230 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1231 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1232 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1233 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1234 pic14Mnemonics[POC_INCF] = &pciINCF;
1235 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1236 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1237 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1238 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1239 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1240 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1241 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1242 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1243 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1244 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1245 pic14Mnemonics[POC_NOP] = &pciNOP;
1246 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1247 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1248 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1249 pic14Mnemonics[POC_RLF] = &pciRLF;
1250 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1251 pic14Mnemonics[POC_RRF] = &pciRRF;
1252 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1253 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1254 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1255 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1256 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1257 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1258 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1259 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1260 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1261 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1263 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1264 if(pic14Mnemonics[i])
1265 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1266 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1269 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1270 pci = hTabNextItem(pic14MnemonicsHash, &key);
1273 mnemonics_initialized = 1;
1276 int getpCodePeepCommand(char *cmd);
1278 int getpCode(char *mnem,unsigned dest)
1281 pCodeInstruction *pci;
1282 int key = mnem2key(mnem);
1284 if(!mnemonics_initialized)
1285 pic14initMnemonics();
1287 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1291 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1292 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1296 pci = hTabNextItemWK (pic14MnemonicsHash);
1303 /*-----------------------------------------------------------------*
1304 * pic14initpCodePeepCommands
1306 *-----------------------------------------------------------------*/
1307 void pic14initpCodePeepCommands(void)
1315 hTabAddItem(&pic14pCodePeepCommandsHash,
1316 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1318 } while (peepCommands[i].cmd);
1320 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1323 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1324 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1329 /*-----------------------------------------------------------------
1332 *-----------------------------------------------------------------*/
1334 int getpCodePeepCommand(char *cmd)
1338 int key = mnem2key(cmd);
1341 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1344 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1345 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1349 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1356 char getpBlock_dbName(pBlock *pb)
1362 return pb->cmemmap->dbName;
1366 void pBlockConvert2ISR(pBlock *pb)
1377 /*-----------------------------------------------------------------*/
1378 /* movepBlock2Head - given the dbname of a pBlock, move all */
1379 /* instances to the front of the doubly linked */
1380 /* list of pBlocks */
1381 /*-----------------------------------------------------------------*/
1383 void movepBlock2Head(char dbName)
1387 pb = the_pFile->pbHead;
1391 if(getpBlock_dbName(pb) == dbName) {
1392 pBlock *pbn = pb->next;
1393 pb->next = the_pFile->pbHead;
1394 the_pFile->pbHead->prev = pb;
1395 the_pFile->pbHead = pb;
1398 pb->prev->next = pbn;
1400 // If the pBlock that we just moved was the last
1401 // one in the link of all of the pBlocks, then we
1402 // need to point the tail to the block just before
1403 // the one we moved.
1404 // Note: if pb->next is NULL, then pb must have
1405 // been the last pBlock in the chain.
1408 pbn->prev = pb->prev;
1410 the_pFile->pbTail = pb->prev;
1421 void copypCode(FILE *of, char dbName)
1425 if(!of || !the_pFile)
1428 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1429 if(getpBlock_dbName(pb) == dbName) {
1436 void pcode_test(void)
1439 DFPRINTF((stderr,"pcode is alive!\n"));
1449 /* create the file name */
1450 strcpy(buffer,srcFileName);
1451 strcat(buffer,".p");
1453 if( !(pFile = fopen(buffer, "w" ))) {
1454 werror(E_FILE_OPEN_ERR,buffer);
1458 fprintf(pFile,"pcode dump\n\n");
1460 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1461 fprintf(pFile,"\n\tNew pBlock\n\n");
1463 fprintf(pFile,"%s",pb->cmemmap->sname);
1465 fprintf(pFile,"internal pblock");
1467 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1468 printpBlock(pFile,pb);
1472 /*-----------------------------------------------------------------*/
1473 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1474 /* ister, RegCond will return the bit being referenced. */
1476 /* fixme - why not just OR in the pcop bit field */
1477 /*-----------------------------------------------------------------*/
1479 static int RegCond(pCodeOp *pcop)
1485 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1486 switch(PCORB(pcop)->bit) {
1500 /*-----------------------------------------------------------------*/
1501 /* newpCode - create and return a newly initialized pCode */
1503 /* fixme - rename this */
1505 /* The purpose of this routine is to create a new Instruction */
1506 /* pCode. This is called by gen.c while the assembly code is being */
1510 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1511 /* (note that the op is analogous to but not the */
1512 /* same thing as the opcode of the instruction.) */
1513 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1516 /* a pointer to the new malloc'd pCode is returned. */
1520 /*-----------------------------------------------------------------*/
1521 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1523 pCodeInstruction *pci ;
1525 if(!mnemonics_initialized)
1526 pic14initMnemonics();
1528 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1530 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1531 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1534 if(pci->inCond == PCC_EXAMINE_PCOP)
1535 pci->inCond = RegCond(pcop);
1537 if(pci->outCond == PCC_EXAMINE_PCOP)
1538 pci->outCond = RegCond(pcop);
1540 pci->pc.prev = pci->pc.next = NULL;
1541 return (pCode *)pci;
1544 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1550 /*-----------------------------------------------------------------*/
1551 /* newpCodeWild - create a "wild" as in wild card pCode */
1553 /* Wild pcodes are used during the peep hole optimizer to serve */
1554 /* as place holders for any instruction. When a snippet of code is */
1555 /* compared to a peep hole rule, the wild card opcode will match */
1556 /* any instruction. However, the optional operand and label are */
1557 /* additional qualifiers that must also be matched before the */
1558 /* line (of assembly code) is declared matched. Note that the */
1559 /* operand may be wild too. */
1561 /* Note, a wild instruction is specified just like a wild var: */
1562 /* %4 ; A wild instruction, */
1563 /* See the peeph.def file for additional examples */
1565 /*-----------------------------------------------------------------*/
1567 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1572 pcw = Safe_calloc(1,sizeof(pCodeWild));
1574 pcw->pci.pc.type = PC_WILD;
1575 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1576 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1577 pcw->pci.pc.pb = NULL;
1579 // pcw->pci.pc.analyze = genericAnalyze;
1580 pcw->pci.pc.destruct = genericDestruct;
1581 pcw->pci.pc.print = genericPrint;
1583 pcw->id = pCodeID; // this is the 'n' in %n
1584 pcw->operand = optional_operand;
1585 pcw->label = optional_label;
1587 pcw->mustBeBitSkipInst = 0;
1588 pcw->mustNotBeBitSkipInst = 0;
1589 pcw->invertBitSkipInst = 0;
1591 return ( (pCode *)pcw);
1595 /*-----------------------------------------------------------------*/
1596 /* newPcodeInlineP - create a new pCode from a char string */
1597 /*-----------------------------------------------------------------*/
1600 pCode *newpCodeInlineP(char *cP)
1605 pcc = Safe_calloc(1,sizeof(pCodeComment));
1607 pcc->pc.type = PC_INLINE;
1608 pcc->pc.prev = pcc->pc.next = NULL;
1609 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1612 // pcc->pc.analyze = genericAnalyze;
1613 pcc->pc.destruct = genericDestruct;
1614 pcc->pc.print = genericPrint;
1617 pcc->comment = Safe_strdup(cP);
1619 pcc->comment = NULL;
1621 return ( (pCode *)pcc);
1625 /*-----------------------------------------------------------------*/
1626 /* newPcodeCharP - create a new pCode from a char string */
1627 /*-----------------------------------------------------------------*/
1629 pCode *newpCodeCharP(char *cP)
1634 pcc = Safe_calloc(1,sizeof(pCodeComment));
1636 pcc->pc.type = PC_COMMENT;
1637 pcc->pc.prev = pcc->pc.next = NULL;
1638 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1641 // pcc->pc.analyze = genericAnalyze;
1642 pcc->pc.destruct = genericDestruct;
1643 pcc->pc.print = genericPrint;
1646 pcc->comment = Safe_strdup(cP);
1648 pcc->comment = NULL;
1650 return ( (pCode *)pcc);
1654 /*-----------------------------------------------------------------*/
1655 /* newpCodeFunction - */
1656 /*-----------------------------------------------------------------*/
1659 pCode *newpCodeFunction(char *mod,char *f)
1663 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1664 //_ALLOC(pcf,sizeof(pCodeFunction));
1666 pcf->pc.type = PC_FUNCTION;
1667 pcf->pc.prev = pcf->pc.next = NULL;
1668 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1671 // pcf->pc.analyze = genericAnalyze;
1672 pcf->pc.destruct = genericDestruct;
1673 pcf->pc.print = pCodePrintFunction;
1676 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1677 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1678 strcpy(pcf->modname,mod);
1680 pcf->modname = NULL;
1683 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1684 pcf->fname = Safe_calloc(1,strlen(f)+1);
1685 strcpy(pcf->fname,f);
1689 return ( (pCode *)pcf);
1693 /*-----------------------------------------------------------------*/
1695 /*-----------------------------------------------------------------*/
1698 pCode *newpCodeFlow(void )
1702 //_ALLOC(pcflow,sizeof(pCodeFlow));
1703 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1705 pcflow->pc.type = PC_FLOW;
1706 pcflow->pc.prev = pcflow->pc.next = NULL;
1707 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1708 pcflow->pc.pb = NULL;
1710 // pcflow->pc.analyze = genericAnalyze;
1711 pcflow->pc.destruct = genericDestruct;
1712 pcflow->pc.print = genericPrint;
1714 pcflow->pc.seq = GpcFlowSeq++;
1717 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1719 pcflow->from = pcflow->to = NULL;
1721 pcflow->inCond = PCC_NONE;
1722 pcflow->outCond = PCC_NONE;
1725 return ( (pCode *)pcflow);
1729 /*-----------------------------------------------------------------*/
1730 /* pCodeLabelDestruct - free memory used by a label. */
1731 /*-----------------------------------------------------------------*/
1732 static void pCodeLabelDestruct(pCode *pc)
1738 if((pc->type == PC_LABEL) && PCL(pc)->label)
1739 free(PCL(pc)->label);
1745 pCode *newpCodeLabel(char *name, int key)
1751 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1753 pcl->pc.type = PC_LABEL;
1754 pcl->pc.prev = pcl->pc.next = NULL;
1755 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1758 // pcl->pc.analyze = genericAnalyze;
1759 pcl->pc.destruct = pCodeLabelDestruct;
1760 pcl->pc.print = pCodePrintLabel;
1766 sprintf(s,"_%05d_DS_",key);
1771 pcl->label = Safe_strdup(s);
1774 return ( (pCode *)pcl);
1779 /*-----------------------------------------------------------------*/
1780 /* newpBlock - create and return a pointer to a new pBlock */
1781 /*-----------------------------------------------------------------*/
1782 pBlock *newpBlock(void)
1787 PpB = Safe_calloc(1,sizeof(pBlock) );
1788 PpB->next = PpB->prev = NULL;
1790 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1791 PpB->tregisters = NULL;
1798 /*-----------------------------------------------------------------*/
1799 /* newpCodeChain - create a new chain of pCodes */
1800 /*-----------------------------------------------------------------*
1802 * This function will create a new pBlock and the pointer to the
1803 * pCode that is passed in will be the first pCode in the block.
1804 *-----------------------------------------------------------------*/
1807 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1810 pBlock *pB = newpBlock();
1812 pB->pcHead = pB->pcTail = pc;
1819 /*-----------------------------------------------------------------*/
1820 /* newpCodeOpLabel - Create a new label given the key */
1821 /* Note, a negative key means that the label is part of wild card */
1822 /* (and hence a wild card label) used in the pCodePeep */
1823 /* optimizations). */
1824 /*-----------------------------------------------------------------*/
1826 pCodeOp *newpCodeOpLabel(char *name, int key)
1829 static int label_key=-1;
1833 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1834 pcop->type = PO_LABEL;
1839 sprintf(s=buffer,"_%05d_DS_",key);
1841 s = name, key = label_key--;
1844 pcop->name = Safe_strdup(s);
1846 ((pCodeOpLabel *)pcop)->key = key;
1851 /*-----------------------------------------------------------------*/
1852 /*-----------------------------------------------------------------*/
1853 pCodeOp *newpCodeOpLit(int lit)
1859 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1860 pcop->type = PO_LITERAL;
1864 sprintf(s,"0x%02x",lit);
1866 pcop->name = Safe_strdup(s);
1869 ((pCodeOpLit *)pcop)->lit = lit;
1874 /*-----------------------------------------------------------------*/
1875 /*-----------------------------------------------------------------*/
1876 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
1880 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1881 pcop->type = PO_IMMEDIATE;
1883 pcop->name = Safe_strdup(name);
1884 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
1890 PCOI(pcop)->index = index;
1891 PCOI(pcop)->offset = offset;
1892 PCOI(pcop)->_const = code_space;
1897 /*-----------------------------------------------------------------*/
1898 /*-----------------------------------------------------------------*/
1899 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
1905 if(!pcwb || !subtype) {
1906 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1910 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1911 pcop->type = PO_WILD;
1912 sprintf(s,"%%%d",id);
1913 pcop->name = Safe_strdup(s);
1915 PCOW(pcop)->id = id;
1916 PCOW(pcop)->pcwb = pcwb;
1917 PCOW(pcop)->subtype = subtype;
1918 PCOW(pcop)->matched = NULL;
1923 /*-----------------------------------------------------------------*/
1924 /*-----------------------------------------------------------------*/
1925 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1929 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1930 pcop->type = PO_GPR_BIT;
1932 pcop->name = Safe_strdup(s);
1936 PCORB(pcop)->bit = bit;
1937 PCORB(pcop)->inBitSpace = inBitSpace;
1942 /*-----------------------------------------------------------------*
1943 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
1945 * If rIdx >=0 then a specific register from the set of registers
1946 * will be selected. If rIdx <0, then a new register will be searched
1948 *-----------------------------------------------------------------*/
1950 pCodeOp *newpCodeOpReg(int rIdx)
1954 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1959 PCOR(pcop)->rIdx = rIdx;
1960 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1962 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
1965 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1966 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
1969 pcop->type = PCOR(pcop)->r->pc_type;
1974 pCodeOp *newpCodeOpRegFromStr(char *name)
1978 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1979 PCOR(pcop)->r = allocRegByName(name, 1);
1980 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1981 pcop->type = PCOR(pcop)->r->pc_type;
1982 pcop->name = PCOR(pcop)->r->name;
1987 /*-----------------------------------------------------------------*/
1988 /*-----------------------------------------------------------------*/
1990 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1997 pcop = newpCodeOpBit(name, -1,0);
2001 pcop = newpCodeOpLit(-1);
2005 pcop = newpCodeOpLabel(NULL,-1);
2008 pcop = newpCodeOpReg(-1);
2012 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2015 pcop->name = Safe_strdup(name);
2023 /*-----------------------------------------------------------------*/
2024 /*-----------------------------------------------------------------*/
2025 void pCodeConstString(char *name, char *value)
2029 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2034 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2038 sprintf(buffer,"; %s = %s",name,value);
2040 addpCode2pBlock(pb,newpCodeCharP(buffer));
2041 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2044 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2050 /*-----------------------------------------------------------------*/
2051 /*-----------------------------------------------------------------*/
2052 void pCodeReadCodeTable(void)
2056 fprintf(stderr, " %s\n",__FUNCTION__);
2058 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2062 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2063 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2064 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2065 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2067 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2068 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2069 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2070 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2075 /*-----------------------------------------------------------------*/
2076 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2077 /*-----------------------------------------------------------------*/
2078 void addpCode2pBlock(pBlock *pb, pCode *pc)
2081 /* If this is the first pcode to be added to a block that
2082 * was initialized with a NULL pcode, then go ahead and
2083 * make this pcode the head and tail */
2084 pb->pcHead = pb->pcTail = pc;
2086 pb->pcTail->next = pc;
2087 pc->prev = pb->pcTail;
2094 /*-----------------------------------------------------------------*/
2095 /* addpBlock - place a pBlock into the pFile */
2096 /*-----------------------------------------------------------------*/
2097 void addpBlock(pBlock *pb)
2099 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2102 /* First time called, we'll pass through here. */
2103 //_ALLOC(the_pFile,sizeof(pFile));
2104 the_pFile = Safe_calloc(1,sizeof(pFile));
2105 the_pFile->pbHead = the_pFile->pbTail = pb;
2106 the_pFile->functions = NULL;
2110 the_pFile->pbTail->next = pb;
2111 pb->prev = the_pFile->pbTail;
2113 the_pFile->pbTail = pb;
2116 /*-----------------------------------------------------------------*/
2117 /* printpCode - write the contents of a pCode to a file */
2118 /*-----------------------------------------------------------------*/
2119 void printpCode(FILE *of, pCode *pc)
2130 fprintf(of,"warning - unable to print pCode\n");
2133 /*-----------------------------------------------------------------*/
2134 /* printpBlock - write the contents of a pBlock to a file */
2135 /*-----------------------------------------------------------------*/
2136 void printpBlock(FILE *of, pBlock *pb)
2146 for(pc = pb->pcHead; pc; pc = pc->next)
2151 /*-----------------------------------------------------------------*/
2153 /* pCode processing */
2157 /*-----------------------------------------------------------------*/
2159 static void unlinkPC(pCode *pc)
2165 pc->prev->next = pc->next;
2167 pc->next->prev = pc->prev;
2169 pc->prev = pc->next = NULL;
2172 static void genericDestruct(pCode *pc)
2174 fprintf(stderr,"warning, calling default pCode destructor\n");
2183 /*-----------------------------------------------------------------*/
2184 /*-----------------------------------------------------------------*/
2185 void pBlockRegs(FILE *of, pBlock *pb)
2190 r = setFirstItem(pb->tregisters);
2192 r = setNextItem(pb->tregisters);
2197 /*-----------------------------------------------------------------*/
2198 /*-----------------------------------------------------------------*/
2199 char *get_op(pCodeOp *pcop)
2202 static char buffer[50];
2208 switch(pcop->type) {
2211 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2212 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2214 return PCOR(pcop)->r->name;
2217 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2218 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2222 // return PCOR(pcc->pcop)->r)->name;
2225 size = sizeof(buffer);
2226 //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2227 if(PCOI(pcop)->_const) {
2229 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2230 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2233 8 * PCOI(pcop)->offset );
2235 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2238 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2239 SAFE_snprintf(&s,&size,"(%s + %d)",
2241 PCOI(pcop)->index );
2243 SAFE_snprintf(&s,&size,"%s",pcop->name);
2250 size = sizeof(buffer);
2251 if( PCOR(pcop)->instance) {
2252 SAFE_snprintf(&s,&size,"(%s + %d)",
2254 PCOR(pcop)->instance );
2255 //fprintf(stderr,"PO_DIR %s\n",buffer);
2257 SAFE_snprintf(&s,&size,"%s",pcop->name);
2267 return "NO operand";
2271 /*-----------------------------------------------------------------*/
2272 /*-----------------------------------------------------------------*/
2273 static char *get_op_from_instruction( pCodeInstruction *pcc)
2277 return get_op(pcc->pcop);
2279 return ("ERROR Null: "__FUNCTION__);
2283 /*-----------------------------------------------------------------*/
2284 /*-----------------------------------------------------------------*/
2285 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2288 fprintf(of,"pcodeopprint\n");
2291 char *pCode2str(char *str, int size, pCode *pc)
2299 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2301 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2303 if(PCI(pc)->isBitInst) {
2304 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2305 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2306 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2307 PCI(pc)->pcop->name ,
2308 PCI(pc)->pcop->name );
2310 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),
2311 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2312 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2313 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2315 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2316 //PCI(pc)->pcop->t.bit );
2319 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2320 if( PCI(pc)->num_ops == 2)
2321 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2323 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2326 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2328 if( PCI(pc)->num_ops == 2)
2329 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2337 /* assuming that comment ends with a \n */
2338 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2342 /* assuming that inline code ends with a \n */
2343 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2347 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2350 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2353 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2356 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2364 /*-----------------------------------------------------------------*/
2365 /* genericPrint - the contents of a pCode to a file */
2366 /*-----------------------------------------------------------------*/
2367 static void genericPrint(FILE *of, pCode *pc)
2375 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2379 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2383 // If the opcode has a label, print that first
2385 pBranch *pbl = PCI(pc)->label;
2386 while(pbl && pbl->pc) {
2387 if(pbl->pc->type == PC_LABEL)
2388 pCodePrintLabel(of, pbl->pc);
2397 pCode2str(str, 256, pc);
2399 fprintf(of,"%s",str);
2402 fprintf(of, "\t;key=%03x",pc->seq);
2404 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2408 pBranch *dpb = pc->to; // debug
2410 switch ( dpb->pc->type) {
2412 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2415 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2418 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2421 fprintf(of, "\t;flow");
2435 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2436 if(PCW(pc)->pci.label)
2437 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2439 if(PCW(pc)->operand) {
2440 fprintf(of,";\toperand ");
2441 pCodeOpPrint(of,PCW(pc)->operand );
2446 fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2451 fprintf(of,"unknown pCode type %d\n",pc->type);
2456 /*-----------------------------------------------------------------*/
2457 /* pCodePrintFunction - prints function begin/end */
2458 /*-----------------------------------------------------------------*/
2460 static void pCodePrintFunction(FILE *of, pCode *pc)
2466 if( ((pCodeFunction *)pc)->modname)
2467 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2469 if(PCF(pc)->fname) {
2470 pBranch *exits = PCF(pc)->to;
2472 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2475 exits = exits->next;
2478 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2481 if((PCF(pc)->from &&
2482 PCF(pc)->from->pc->type == PC_FUNCTION &&
2483 PCF(PCF(pc)->from->pc)->fname) )
2484 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2486 fprintf(of,"; exit point [can't find entry point]\n");
2489 /*-----------------------------------------------------------------*/
2490 /* pCodePrintLabel - prints label */
2491 /*-----------------------------------------------------------------*/
2493 static void pCodePrintLabel(FILE *of, pCode *pc)
2500 fprintf(of,"%s\n",PCL(pc)->label);
2501 else if (PCL(pc)->key >=0)
2502 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2504 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2507 /*-----------------------------------------------------------------*/
2508 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2509 /* remove it if it is found. */
2510 /*-----------------------------------------------------------------*/
2511 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2518 if(pcl->type == PC_OPCODE)
2519 b = PCI(pcl)->label;
2521 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2531 bprev->next = b->next; /* Not first pCode in chain */
2535 PCI(pcl)->label = b->next; /* First pCode in chain */
2538 return; /* A label can't occur more than once */
2555 bprev->next = b->next; /* Not first pCode in chain */
2559 pcl->label = b->next; /* First pCode in chain */
2562 return; /* A label can't occur more than once */
2570 /*-----------------------------------------------------------------*/
2571 /*-----------------------------------------------------------------*/
2572 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2588 /*-----------------------------------------------------------------*/
2589 /* pBranchLink - given two pcodes, this function will link them */
2590 /* together through their pBranches */
2591 /*-----------------------------------------------------------------*/
2592 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2596 // Declare a new branch object for the 'from' pCode.
2598 //_ALLOC(b,sizeof(pBranch));
2599 b = Safe_calloc(1,sizeof(pBranch));
2600 b->pc = PCODE(t); // The link to the 'to' pCode.
2603 f->to = pBranchAppend(f->to,b);
2605 // Now do the same for the 'to' pCode.
2607 //_ALLOC(b,sizeof(pBranch));
2608 b = Safe_calloc(1,sizeof(pBranch));
2612 t->from = pBranchAppend(t->from,b);
2617 /*-----------------------------------------------------------------*/
2618 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2620 /*-----------------------------------------------------------------*/
2621 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2634 /*-----------------------------------------------------------------*/
2635 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2636 /*-----------------------------------------------------------------*/
2637 static void pCodeUnlink(pCode *pc)
2642 if(!pc->prev || !pc->next) {
2643 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2647 /* first remove the pCode from the chain */
2648 pc->prev->next = pc->next;
2649 pc->next->prev = pc->prev;
2651 /* Now for the hard part... */
2653 /* Remove the branches */
2657 pc1 = pb1->pc; /* Get the pCode that branches to the
2658 * one we're unlinking */
2660 /* search for the link back to this pCode (the one we're
2662 if(pb2 = pBranchFind(pc1->to,pc)) {
2663 pb2->pc = pc->to->pc; // make the replacement
2665 /* if the pCode we're unlinking contains multiple 'to'
2666 * branches (e.g. this a skip instruction) then we need
2667 * to copy these extra branches to the chain. */
2669 pBranchAppend(pb2, pc->to->next);
2678 /*-----------------------------------------------------------------*/
2679 /*-----------------------------------------------------------------*/
2681 static void genericAnalyze(pCode *pc)
2691 // Go through the pCodes that are in pCode chain and link
2692 // them together through the pBranches. Note, the pCodes
2693 // are linked together as a contiguous stream like the
2694 // assembly source code lines. The linking here mimics this
2695 // except that comments are not linked in.
2697 pCode *npc = pc->next;
2699 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2700 pBranchLink(pc,npc);
2705 /* reached the end of the pcode chain without finding
2706 * an instruction we could link to. */
2710 fprintf(stderr,"analyze PC_FLOW\n");
2717 /*-----------------------------------------------------------------*/
2718 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2722 if(pc->type == PC_LABEL) {
2723 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2726 if(pc->type == PC_OPCODE) {
2727 pbr = PCI(pc)->label;
2729 if(pbr->pc->type == PC_LABEL) {
2730 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2740 /*-----------------------------------------------------------------*/
2741 /* findLabel - Search the pCode for a particular label */
2742 /*-----------------------------------------------------------------*/
2743 pCode * findLabel(pCodeOpLabel *pcop_label)
2751 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2752 for(pc = pb->pcHead; pc; pc = pc->next)
2753 if(compareLabel(pc,pcop_label))
2758 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2762 /*-----------------------------------------------------------------*/
2763 /* findNextpCode - given a pCode, find the next of type 'pct' */
2764 /* in the linked list */
2765 /*-----------------------------------------------------------------*/
2766 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2779 /*-----------------------------------------------------------------*/
2780 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2781 /* in the linked list */
2782 /*-----------------------------------------------------------------*/
2783 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2795 /*-----------------------------------------------------------------*/
2796 /* findNextInstruction - given a pCode, find the next instruction */
2797 /* in the linked list */
2798 /*-----------------------------------------------------------------*/
2799 pCode * findNextInstruction(pCode *pc)
2803 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2806 fprintf(stderr,"findNextInstruction: ");
2807 printpCode(stderr, pc);
2812 //fprintf(stderr,"Couldn't find instruction\n");
2816 /*-----------------------------------------------------------------*/
2817 /* findFunctionEnd - given a pCode find the end of the function */
2818 /* that contains it t */
2819 /*-----------------------------------------------------------------*/
2820 pCode * findFunctionEnd(pCode *pc)
2824 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2830 fprintf(stderr,"Couldn't find function end\n");
2835 /*-----------------------------------------------------------------*/
2836 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2837 /* instruction with which it is associated. */
2838 /*-----------------------------------------------------------------*/
2839 static void AnalyzeLabel(pCode *pc)
2848 static void AnalyzeGOTO(pCode *pc)
2851 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2855 static void AnalyzeSKIP(pCode *pc)
2858 pBranchLink(pc,findNextInstruction(pc->next));
2859 pBranchLink(pc,findNextInstruction(pc->next->next));
2863 static void AnalyzeRETURN(pCode *pc)
2866 // branch_link(pc,findFunctionEnd(pc->next));
2872 /*-----------------------------------------------------------------*/
2873 /*-----------------------------------------------------------------*/
2874 regs * getRegFromInstruction(pCode *pc)
2879 PCI(pc)->num_ops == 0 )
2882 switch(PCI(pc)->pcop->type) {
2885 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2889 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2890 return PCOR(PCI(pc)->pcop)->r;
2893 //fprintf(stderr, "getRegFromInstruction - immediate\n");
2894 return NULL; // PCOR(PCI(pc)->pcop)->r;
2897 return PCOR(PCI(pc)->pcop)->r;
2900 //fprintf(stderr, "getRegFromInstruction - dir\n");
2901 return PCOR(PCI(pc)->pcop)->r;
2903 //fprintf(stderr, "getRegFromInstruction - literal\n");
2907 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2908 //genericPrint(stderr, pc);
2916 /*-----------------------------------------------------------------*/
2917 /*-----------------------------------------------------------------*/
2919 void AnalyzepBlock(pBlock *pb)
2926 /* Find all of the registers used in this pBlock
2927 * by looking at each instruction and examining it's
2930 for(pc = pb->pcHead; pc; pc = pc->next) {
2932 /* Is this an instruction with operands? */
2933 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2935 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2937 /* Loop through all of the registers declared so far in
2938 this block and see if we find this one there */
2940 regs *r = setFirstItem(pb->tregisters);
2943 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2944 PCOR(PCI(pc)->pcop)->r = r;
2947 r = setNextItem(pb->tregisters);
2951 /* register wasn't found */
2952 r = Safe_calloc(1, sizeof(regs));
2953 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2954 addSet(&pb->tregisters, r);
2955 PCOR(PCI(pc)->pcop)->r = r;
2956 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2958 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2961 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2962 if(PCOR(PCI(pc)->pcop)->r) {
2963 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2964 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2966 if(PCI(pc)->pcop->name)
2967 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2969 fprintf(stderr,"ERROR: NULL register\n");
2978 /*-----------------------------------------------------------------*/
2980 /*-----------------------------------------------------------------*/
2981 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2983 void InsertpFlow(pCode *pc, pCode **pflow)
2985 PCFL(*pflow)->end = pc;
2987 if(!pc || !pc->next)
2990 *pflow = newpCodeFlow();
2991 pCodeInsertAfter(pc, *pflow);
2994 /*-----------------------------------------------------------------*/
2995 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
2996 /* the flow blocks. */
2998 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2999 * point the instruction flow changes.
3001 /*-----------------------------------------------------------------*/
3002 void BuildFlow(pBlock *pb)
3005 pCode *last_pci=NULL;
3012 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3013 /* Insert a pCodeFlow object at the beginning of a pBlock */
3015 pflow = newpCodeFlow(); /* Create a new Flow object */
3016 pflow->next = pb->pcHead; /* Make the current head the next object */
3017 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3018 pb->pcHead = pflow; /* Make the Flow object the head */
3021 for( pc = findNextInstruction(pb->pcHead);
3022 (pc=findNextInstruction(pc)) != NULL; ) {
3025 PCI(pc)->pcflow = PCFL(pflow);
3027 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
3029 /* The instruction immediately following this one
3030 * marks the beginning of a new flow segment */
3032 InsertpFlow(pc, &pflow);
3035 } else if (PCI_HAS_LABEL(pc)) {
3037 /* This instruction marks the beginning of a
3038 * new flow segment */
3042 InsertpFlow(pc->prev, &pflow);
3044 PCI(pc)->pcflow = PCFL(pflow);
3051 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3052 PCFL(pflow)->end = pb->pcTail;
3055 /*-----------------------------------------------------------------*/
3056 /*-----------------------------------------------------------------*/
3057 void dumpCond(int cond)
3060 static char *pcc_str[] = {
3074 int ncond = sizeof(pcc_str) / sizeof(char *);
3077 fprintf(stderr, "0x%04X\n",cond);
3079 for(i=0,j=1; i<ncond; i++, j<<=1)
3081 fprintf(stderr, " %s\n",pcc_str[i]);
3085 /*-----------------------------------------------------------------*/
3086 /*-----------------------------------------------------------------*/
3087 void FillFlow(pCodeFlow *pcflow)
3096 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3098 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3100 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3109 int inCond = PCI(pc)->inCond;
3110 int outCond = PCI(pc)->outCond;
3112 if( (reg = getRegFromInstruction(pc)) != NULL) {
3113 if(isSTATUS_REG(reg)) {
3115 //fprintf(stderr, " FillFlow - Status register\n");
3117 /* Check to see if the register banks are changing */
3118 if(PCI(pc)->isModReg) {
3120 pCodeOp *pcop = PCI(pc)->pcop;
3121 switch(PCI(pc)->op) {
3123 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3124 fprintf(stderr, " FillFlow - Set RP0\n");
3125 //outCond |= PCC_REG_BANK1;
3126 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3127 fprintf(stderr, " FillFlow - Set RP1\n");
3128 //outCond |= PCC_REG_BANK3;
3132 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3133 fprintf(stderr, " FillFlow - Clr RP0\n");
3134 //outCond |= PCC_REG_BANK1;
3135 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3136 fprintf(stderr, " FillFlow - Clr RP1\n");
3137 //outCond |= PCC_REG_BANK3;
3141 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3142 genericPrint(stderr, pc);
3147 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3151 pcflow->inCond |= (inCond & ~pcflow->outCond);
3152 pcflow->outCond |= outCond;
3157 pc = findNextpCode(pc->next, PC_OPCODE);
3158 } while (pc && (pc != pcflow->end));
3162 fprintf(stderr, " FillFlow - Bad end of flow\n");
3165 fprintf(stderr, " FillFlow inCond: ");
3166 dumpCond(pcflow->inCond);
3167 fprintf(stderr, " FillFlow outCond: ");
3168 dumpCond(pcflow->outCond);
3171 /*-----------------------------------------------------------------*/
3172 /*-----------------------------------------------------------------*/
3173 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3176 if(!from || !to || !to->pcflow || !from->pcflow)
3179 addSet(&(from->pcflow->to), to->pcflow);
3180 addSet(&(to->pcflow->from), from->pcflow);
3184 /*-----------------------------------------------------------------*/
3185 /*-----------------------------------------------------------------*/
3186 void LinkFlow(pBlock *pb)
3193 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3194 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3195 pcflow = pcflow->next) {
3198 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3200 //FillFlow(PCFL(pcflow));
3202 pc = PCFL(pcflow)->end;
3204 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3205 if(isPCI_SKIP(pc)) {
3206 //fprintf(stderr, "ends with skip\n");
3207 pct=findNextInstruction(pc->next);
3208 LinkFlow_pCode(PCI(pc),PCI(pct));
3209 pct=findNextInstruction(pct->next);
3210 LinkFlow_pCode(PCI(pc),PCI(pct));
3214 if(isPCI_BRANCH(pc)) {
3215 //fprintf(stderr, "ends with branch\n");
3221 fprintf(stderr, "has an unrecognized ending:\n");
3222 pc->print(stderr,pc);
3225 fprintf(stderr, "has no end pcode\n");
3230 /*-----------------------------------------------------------------*/
3231 /*-----------------------------------------------------------------*/
3232 int OptimizepBlock(pBlock *pb)
3237 if(!pb || !peepOptimizing)
3240 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3241 for(pc = pb->pcHead; pc; pc = pc->next)
3242 matches += pCodePeepMatchRule(pc);
3244 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3249 /*-----------------------------------------------------------------*/
3250 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3251 /*-----------------------------------------------------------------*/
3252 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3256 for(pc = pcs; pc; pc = pc->next) {
3258 if((pc->type == PC_OPCODE) &&
3260 (PCI(pc)->pcop->type == PO_LABEL) &&
3261 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3269 /*-----------------------------------------------------------------*/
3270 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3271 /* pCode chain if they're not used. */
3272 /*-----------------------------------------------------------------*/
3273 void pBlockRemoveUnusedLabels(pBlock *pb)
3275 pCode *pc; pCodeLabel *pcl;
3280 for(pc = pb->pcHead; pc; pc = pc->next) {
3282 if(pc->type == PC_LABEL)
3284 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3285 pcl = PCL(PCI(pc)->label->pc);
3288 /* This pCode is a label, so search the pBlock to see if anyone
3291 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3292 /* Couldn't find an instruction that refers to this label
3293 * So, unlink the pCode label from it's pCode chain
3294 * and destroy the label */
3296 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3298 if(pc->type == PC_LABEL) {
3300 pCodeLabelDestruct(pc);
3302 unlinkpCodeFromBranch(pc, PCODE(pcl));
3303 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3314 /*-----------------------------------------------------------------*/
3315 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3316 /* chain and put them into pBranches that are */
3317 /* associated with the appropriate pCode */
3319 /*-----------------------------------------------------------------*/
3320 void pBlockMergeLabels(pBlock *pb)
3323 pCode *pc, *pcnext=NULL;
3328 /* First, Try to remove any unused labels */
3329 //pBlockRemoveUnusedLabels(pb);
3331 /* Now loop through the pBlock and merge the labels with the opcodes */
3333 for(pc = pb->pcHead; pc; pc = pc->next) {
3335 if(pc->type == PC_LABEL) {
3336 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3337 if( !(pcnext = findNextInstruction(pc)) )
3338 return; // Couldn't find an instruction associated with this label
3340 // Unlink the pCode label from it's pCode chain
3343 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3344 // And link it into the instruction's pBranch labels. (Note, since
3345 // it's possible to have multiple labels associated with one instruction
3346 // we must provide a means to accomodate the additional labels. Thus
3347 // the labels are placed into the singly-linked list "label" as
3348 // opposed to being a single member of the pCodeInstruction.)
3350 //_ALLOC(pbr,sizeof(pBranch));
3351 pbr = Safe_calloc(1,sizeof(pBranch));
3355 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3363 pBlockRemoveUnusedLabels(pb);
3367 /*-----------------------------------------------------------------*/
3368 /*-----------------------------------------------------------------*/
3369 void OptimizepCode(char dbName)
3371 #define MAX_PASSES 4
3380 DFPRINTF((stderr," Optimizing pCode\n"));
3383 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3384 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3385 matches += OptimizepBlock(pb);
3388 while(matches && ++passes < MAX_PASSES);
3392 /*-----------------------------------------------------------------*/
3393 /* popCopyGPR2Bit - copy a pcode operator */
3394 /*-----------------------------------------------------------------*/
3396 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3400 pcop = newpCodeOpBit(pc->name, bitval, 0);
3402 if( !( (pcop->type == PO_LABEL) ||
3403 (pcop->type == PO_LITERAL) ||
3404 (pcop->type == PO_STR) ))
3405 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3413 /*-----------------------------------------------------------------*/
3414 /*-----------------------------------------------------------------*/
3415 int InstructionRegBank(pCode *pc)
3419 if( (reg = getRegFromInstruction(pc)) == NULL)
3422 return REG_BANK(reg);
3427 /*-----------------------------------------------------------------*/
3428 /*-----------------------------------------------------------------*/
3429 void FixRegisterBanking(pBlock *pb)
3441 pc = findNextpCode(pb->pcHead, PC_FLOW);
3444 /* loop through all of the flow blocks with in one pblock */
3446 //fprintf(stderr,"Register banking\n");
3449 /* at this point, pc should point to a PC_FLOW object */
3452 /* for each flow block, determine the register banking
3457 //genericPrint(stderr, pc);
3459 reg = getRegFromInstruction(pc);
3462 fprintf(stderr, " %s ",reg->name);
3463 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3467 if(reg && REG_BANK(reg)!=cur_bank) {
3468 /* Examine the instruction before this one to make sure it is
3469 * not a skip type instruction */
3470 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3471 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3472 int b = cur_bank ^ REG_BANK(reg);
3474 //fprintf(stderr, "Cool! can switch banks\n");
3475 cur_bank = REG_BANK(reg);
3477 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3478 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3479 pCodeInsertAfter(pc->prev, new_pc);
3480 if(PCI(pc)->label) {
3481 PCI(new_pc)->label = PCI(pc)->label;
3482 PCI(pc)->label = NULL;
3485 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3486 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3487 pCodeInsertAfter(pc, new_pc);
3493 //fprintf(stderr, "Bummer can't switch banks\n");
3501 } while(pc && !(isPCFL(pc)));
3503 if(pcprev && cur_bank) {
3504 /* Brute force - make sure that we point to bank 0 at the
3505 * end of each flow block */
3506 new_pc = newpCode(POC_BCF,
3507 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3508 pCodeInsertAfter(pcprev, new_pc);
3516 void pBlockDestruct(pBlock *pb)
3527 /*-----------------------------------------------------------------*/
3528 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3529 /* name dbName and combine them */
3530 /* into one block */
3531 /*-----------------------------------------------------------------*/
3532 void mergepBlocks(char dbName)
3535 pBlock *pb, *pbmerged = NULL,*pbn;
3537 pb = the_pFile->pbHead;
3539 //fprintf(stderr," merging blocks named %c\n",dbName);
3543 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3544 if( getpBlock_dbName(pb) == dbName) {
3546 //fprintf(stderr," merged block %c\n",dbName);
3551 addpCode2pBlock(pbmerged, pb->pcHead);
3552 /* addpCode2pBlock doesn't handle the tail: */
3553 pbmerged->pcTail = pb->pcTail;
3555 pb->prev->next = pbn;
3557 pbn->prev = pb->prev;
3562 //printpBlock(stderr, pbmerged);
3569 /*-----------------------------------------------------------------*/
3570 /* AnalyzeBanking - Called after the memory addresses have been */
3571 /* assigned to the registers. */
3573 /*-----------------------------------------------------------------*/
3574 void AnalyzeBanking(void)
3583 /* Phase 2 - Flow Analysis
3585 * In this phase, the pCode is partition into pCodeFlow
3586 * blocks. The flow blocks mark the points where a continuous
3587 * stream of instructions changes flow (e.g. because of
3588 * a call or goto or whatever).
3591 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3594 /* Phase 2 - Flow Analysis - linking flow blocks
3596 * In this phase, the individual flow blocks are examined
3597 * to determine their order of excution.
3600 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3603 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3604 FixRegisterBanking(pb);
3607 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3609 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3610 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3611 pcflow = pcflow->next) {
3613 FillFlow(PCFL(pcflow));
3620 /*-----------------------------------------------------------------*/
3621 /* buildCallTree - look at the flow and extract all of the calls */
3623 /*-----------------------------------------------------------------*/
3624 set *register_usage(pBlock *pb);
3626 void buildCallTree(void )
3637 /* Now build the call tree.
3638 First we examine all of the pCodes for functions.
3639 Keep in mind that the function boundaries coincide
3640 with pBlock boundaries.
3642 The algorithm goes something like this:
3643 We have two nested loops. The outer loop iterates
3644 through all of the pBlocks/functions. The inner
3645 loop iterates through all of the pCodes for
3646 a given pBlock. When we begin iterating through
3647 a pBlock, the variable pc_fstart, pCode of the start
3648 of a function, is cleared. We then search for pCodes
3649 of type PC_FUNCTION. When one is encountered, we
3650 initialize pc_fstart to this and at the same time
3651 associate a new pBranch object that signifies a
3652 branch entry. If a return is found, then this signifies
3653 a function exit point. We'll link the pCodes of these
3654 returns to the matching pc_fstart.
3656 When we're done, a doubly linked list of pBranches
3657 will exist. The head of this list is stored in
3658 `the_pFile', which is the meta structure for all
3659 of the pCode. Look at the printCallTree function
3660 on how the pBranches are linked together.
3663 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3664 pCode *pc_fstart=NULL;
3665 for(pc = pb->pcHead; pc; pc = pc->next) {
3666 if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
3667 if (PCF(pc)->fname) {
3669 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3670 //fprintf(stderr," found main \n");
3671 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3675 //_ALLOC(pbr,sizeof(pBranch));
3676 pbr = Safe_calloc(1,sizeof(pBranch));
3677 pbr->pc = pc_fstart = pc;
3680 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3682 // Here's a better way of doing the same:
3683 addSet(&pb->function_entries, pc);
3686 // Found an exit point in a function, e.g. return
3687 // (Note, there may be more than one return per function)
3689 pBranchLink(PCF(pc_fstart), PCF(pc));
3691 addSet(&pb->function_exits, pc);
3693 } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3694 addSet(&pb->function_calls,pc);
3699 /* Re-allocate the registers so that there are no collisions
3700 * between local variables when one function call another */
3702 pic14_deallocateAllRegs();
3704 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3711 /*-----------------------------------------------------------------*/
3712 /* AnalyzepCode - parse the pCode that has been generated and form */
3713 /* all of the logical connections. */
3715 /* Essentially what's done here is that the pCode flow is */
3717 /*-----------------------------------------------------------------*/
3719 void AnalyzepCode(char dbName)
3730 /* Phase 1 - Register allocation and peep hole optimization
3732 * The first part of the analysis is to determine the registers
3733 * that are used in the pCode. Once that is done, the peep rules
3734 * are applied to the code. We continue to loop until no more
3735 * peep rule optimizations are found (or until we exceed the
3736 * MAX_PASSES threshold).
3738 * When done, the required registers will be determined.
3744 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3746 /* First, merge the labels with the instructions */
3747 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3748 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3750 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3751 //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3752 pBlockMergeLabels(pb);
3759 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3760 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3761 changes += OptimizepBlock(pb);
3764 } while(changes && (i++ < MAX_PASSES));
3769 /*-----------------------------------------------------------------*/
3770 /* ispCodeFunction - returns true if *pc is the pCode of a */
3772 /*-----------------------------------------------------------------*/
3773 bool ispCodeFunction(pCode *pc)
3776 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3782 /*-----------------------------------------------------------------*/
3783 /* findFunction - Search for a function by name (given the name) */
3784 /* in the set of all functions that are in a pBlock */
3785 /* (note - I expect this to change because I'm planning to limit */
3786 /* pBlock's to just one function declaration */
3787 /*-----------------------------------------------------------------*/
3788 pCode *findFunction(char *fname)
3795 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3797 pc = setFirstItem(pb->function_entries);
3800 if((pc->type == PC_FUNCTION) &&
3802 (strcmp(fname, PCF(pc)->fname)==0))
3805 pc = setNextItem(pb->function_entries);
3813 void MarkUsedRegisters(set *regset)
3818 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3819 r2 = pic14_regWithIdx(r1->rIdx);
3825 void pBlockStats(FILE *of, pBlock *pb)
3831 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3833 // for now just print the first element of each set
3834 pc = setFirstItem(pb->function_entries);
3836 fprintf(of,";entry: ");
3839 pc = setFirstItem(pb->function_exits);
3841 fprintf(of,";has an exit\n");
3845 pc = setFirstItem(pb->function_calls);
3847 fprintf(of,";functions called:\n");
3850 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3851 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
3853 pc = setNextItem(pb->function_calls);
3857 r = setFirstItem(pb->tregisters);
3859 int n = elementsInSet(pb->tregisters);
3861 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3864 fprintf(of,"; %s\n",r->name);
3865 r = setNextItem(pb->tregisters);
3870 /*-----------------------------------------------------------------*/
3871 /*-----------------------------------------------------------------*/
3872 static void sequencepCode(void)
3878 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3880 pb->seq = GpCodeSequenceNumber+1;
3882 for( pc = pb->pcHead; pc; pc = pc->next)
3883 pc->seq = ++GpCodeSequenceNumber;
3888 /*-----------------------------------------------------------------*/
3889 /*-----------------------------------------------------------------*/
3890 set *register_usage(pBlock *pb)
3893 set *registers=NULL;
3894 set *registersInCallPath = NULL;
3896 /* check recursion */
3898 pc = setFirstItem(pb->function_entries);
3905 if(pc->type != PC_FUNCTION)
3906 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3908 pc = setFirstItem(pb->function_calls);
3909 for( ; pc; pc = setNextItem(pb->function_calls)) {
3911 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3912 char *dest = get_op_from_instruction(PCI(pc));
3914 pcn = findFunction(dest);
3916 registersInCallPath = register_usage(pcn->pb);
3918 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3923 pBlockStats(stderr,pb); // debug
3926 // Mark the registers in this block as used.
3928 MarkUsedRegisters(pb->tregisters);
3929 if(registersInCallPath) {
3930 /* registers were used in the functions this pBlock has called */
3931 /* so now, we need to see if these collide with the ones we are */
3934 regs *r1,*r2, *newreg;
3936 DFPRINTF((stderr,"comparing registers\n"));
3938 r1 = setFirstItem(registersInCallPath);
3941 r2 = setFirstItem(pb->tregisters);
3943 while(r2 && (r1->type != REG_STK)) {
3945 if(r2->rIdx == r1->rIdx) {
3946 newreg = pic14_findFreeReg(REG_GPR);
3950 DFPRINTF((stderr,"Bummer, no more registers.\n"));
3954 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3955 r1->rIdx, newreg->rIdx));
3956 r2->rIdx = newreg->rIdx;
3957 //if(r2->name) free(r2->name);
3959 r2->name = Safe_strdup(newreg->name);
3963 newreg->wasUsed = 1;
3965 r2 = setNextItem(pb->tregisters);
3968 r1 = setNextItem(registersInCallPath);
3971 /* Collisions have been resolved. Now free the registers in the call path */
3972 r1 = setFirstItem(registersInCallPath);
3974 if(r1->type != REG_STK) {
3975 newreg = pic14_regWithIdx(r1->rIdx);
3978 r1 = setNextItem(registersInCallPath);
3982 // MarkUsedRegisters(pb->registers);
3984 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3987 DFPRINTF((stderr,"returning regs\n"));
3989 DFPRINTF((stderr,"not returning regs\n"));
3991 DFPRINTF((stderr,"pBlock after register optim.\n"));
3992 pBlockStats(stderr,pb); // debug
3998 /*-----------------------------------------------------------------*/
3999 /* printCallTree - writes the call tree to a file */
4001 /*-----------------------------------------------------------------*/
4002 void pct2(FILE *of,pBlock *pb,int indent)
4006 // set *registersInCallPath = NULL;
4009 return;// registers;
4012 return; // registers; //recursion ?
4014 pc = setFirstItem(pb->function_entries);
4021 for(i=0;i<indent;i++) // Indentation
4024 if(pc->type == PC_FUNCTION)
4025 fprintf(of,"%s\n",PCF(pc)->fname);
4030 pc = setFirstItem(pb->function_calls);
4031 for( ; pc; pc = setNextItem(pb->function_calls)) {
4033 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4034 char *dest = get_op_from_instruction(PCI(pc));
4036 pcn = findFunction(dest);
4038 pct2(of,pcn->pb,indent+1);
4040 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4048 fprintf(stderr,"pBlock before register optim.\n");
4049 pBlockStats(stderr,pb); // debug
4051 if(registersInCallPath) {
4052 /* registers were used in the functions this pBlock has called */
4053 /* so now, we need to see if these collide with the ones we are using here */
4055 regs *r1,*r2, *newreg;
4057 fprintf(stderr,"comparing registers\n");
4059 r1 = setFirstItem(registersInCallPath);
4062 r2 = setFirstItem(pb->registers);
4066 if(r2->rIdx == r1->rIdx) {
4067 newreg = pic14_findFreeReg();
4071 fprintf(stderr,"Bummer, no more registers.\n");
4075 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
4076 r1->rIdx, newreg->rIdx);
4077 r2->rIdx = newreg->rIdx;
4078 //if(r2->name) free(r2->name);
4080 r2->name = Safe_strdup(newreg->name);
4084 newreg->wasUsed = 1;
4086 r2 = setNextItem(pb->registers);
4089 r1 = setNextItem(registersInCallPath);
4092 /* Collisions have been resolved. Now free the registers in the call path */
4093 r1 = setFirstItem(registersInCallPath);
4095 newreg = pic14_regWithIdx(r1->rIdx);
4097 r1 = setNextItem(registersInCallPath);
4101 MarkUsedRegisters(pb->registers);
4103 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
4106 fprintf(stderr,"returning regs\n");
4108 fprintf(stderr,"not returning regs\n");
4110 fprintf(stderr,"pBlock after register optim.\n");
4111 pBlockStats(stderr,pb); // debug
4119 /*-----------------------------------------------------------------*/
4120 /* printCallTree - writes the call tree to a file */
4122 /*-----------------------------------------------------------------*/
4124 void printCallTree(FILE *of)
4136 fprintf(of, "\npBlock statistics\n");
4137 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4142 fprintf(of,"Call Tree\n");
4143 pbr = the_pFile->functions;
4147 if(!ispCodeFunction(pc))
4148 fprintf(of,"bug in call tree");
4151 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4153 while(pc->next && !ispCodeFunction(pc->next)) {
4155 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4156 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
4164 /* Re-allocate the registers so that there are no collisions
4165 * between local variables when one function call another */
4167 pic14_deallocateAllRegs();
4169 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4175 fprintf(of,"\n**************\n\na better call tree\n");
4176 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4181 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4182 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));