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))
2809 //fprintf(stderr,"Couldn't find instruction\n");
2813 /*-----------------------------------------------------------------*/
2814 /* findFunctionEnd - given a pCode find the end of the function */
2815 /* that contains it t */
2816 /*-----------------------------------------------------------------*/
2817 pCode * findFunctionEnd(pCode *pc)
2821 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2827 fprintf(stderr,"Couldn't find function end\n");
2832 /*-----------------------------------------------------------------*/
2833 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2834 /* instruction with which it is associated. */
2835 /*-----------------------------------------------------------------*/
2836 static void AnalyzeLabel(pCode *pc)
2845 static void AnalyzeGOTO(pCode *pc)
2848 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2852 static void AnalyzeSKIP(pCode *pc)
2855 pBranchLink(pc,findNextInstruction(pc->next));
2856 pBranchLink(pc,findNextInstruction(pc->next->next));
2860 static void AnalyzeRETURN(pCode *pc)
2863 // branch_link(pc,findFunctionEnd(pc->next));
2869 /*-----------------------------------------------------------------*/
2870 /*-----------------------------------------------------------------*/
2871 regs * getRegFromInstruction(pCode *pc)
2876 PCI(pc)->num_ops == 0 )
2879 switch(PCI(pc)->pcop->type) {
2882 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2886 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2887 return PCOR(PCI(pc)->pcop)->r;
2890 //fprintf(stderr, "getRegFromInstruction - immediate\n");
2891 return NULL; // PCOR(PCI(pc)->pcop)->r;
2894 return PCOR(PCI(pc)->pcop)->r;
2897 //fprintf(stderr, "getRegFromInstruction - dir\n");
2898 return PCOR(PCI(pc)->pcop)->r;
2900 //fprintf(stderr, "getRegFromInstruction - literal\n");
2904 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2905 //genericPrint(stderr, pc);
2913 /*-----------------------------------------------------------------*/
2914 /*-----------------------------------------------------------------*/
2916 void AnalyzepBlock(pBlock *pb)
2923 /* Find all of the registers used in this pBlock
2924 * by looking at each instruction and examining it's
2927 for(pc = pb->pcHead; pc; pc = pc->next) {
2929 /* Is this an instruction with operands? */
2930 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2932 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2934 /* Loop through all of the registers declared so far in
2935 this block and see if we find this one there */
2937 regs *r = setFirstItem(pb->tregisters);
2940 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2941 PCOR(PCI(pc)->pcop)->r = r;
2944 r = setNextItem(pb->tregisters);
2948 /* register wasn't found */
2949 r = Safe_calloc(1, sizeof(regs));
2950 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2951 addSet(&pb->tregisters, r);
2952 PCOR(PCI(pc)->pcop)->r = r;
2953 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2955 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2958 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2959 if(PCOR(PCI(pc)->pcop)->r) {
2960 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2961 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2963 if(PCI(pc)->pcop->name)
2964 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2966 fprintf(stderr,"ERROR: NULL register\n");
2975 /*-----------------------------------------------------------------*/
2977 /*-----------------------------------------------------------------*/
2978 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2980 void InsertpFlow(pCode *pc, pCode **pflow)
2982 PCFL(*pflow)->end = pc;
2984 if(!pc || !pc->next)
2987 *pflow = newpCodeFlow();
2988 pCodeInsertAfter(pc, *pflow);
2991 /*-----------------------------------------------------------------*/
2992 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
2993 /* the flow blocks. */
2995 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2996 * point the instruction flow changes.
2998 /*-----------------------------------------------------------------*/
2999 void BuildFlow(pBlock *pb)
3002 pCode *last_pci=NULL;
3009 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3010 /* Insert a pCodeFlow object at the beginning of a pBlock */
3012 pflow = newpCodeFlow(); /* Create a new Flow object */
3013 pflow->next = pb->pcHead; /* Make the current head the next object */
3014 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3015 pb->pcHead = pflow; /* Make the Flow object the head */
3018 for( pc = findNextInstruction(pb->pcHead);
3019 (pc=findNextInstruction(pc)) != NULL; ) {
3022 PCI(pc)->pcflow = PCFL(pflow);
3024 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
3026 /* The instruction immediately following this one
3027 * marks the beginning of a new flow segment */
3029 InsertpFlow(pc, &pflow);
3032 } else if (PCI_HAS_LABEL(pc)) {
3034 /* This instruction marks the beginning of a
3035 * new flow segment */
3039 InsertpFlow(pc->prev, &pflow);
3041 PCI(pc)->pcflow = PCFL(pflow);
3048 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3049 PCFL(pflow)->end = pb->pcTail;
3052 /*-----------------------------------------------------------------*/
3053 /*-----------------------------------------------------------------*/
3054 void dumpCond(int cond)
3057 static char *pcc_str[] = {
3071 int ncond = sizeof(pcc_str) / sizeof(char *);
3074 fprintf(stderr, "0x%04X\n",cond);
3076 for(i=0,j=1; i<ncond; i++, j<<=1)
3078 fprintf(stderr, " %s\n",pcc_str[i]);
3082 /*-----------------------------------------------------------------*/
3083 /*-----------------------------------------------------------------*/
3084 void FillFlow(pCodeFlow *pcflow)
3093 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3095 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3097 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3106 int inCond = PCI(pc)->inCond;
3107 int outCond = PCI(pc)->outCond;
3109 if( (reg = getRegFromInstruction(pc)) != NULL) {
3110 if(isSTATUS_REG(reg)) {
3112 //fprintf(stderr, " FillFlow - Status register\n");
3114 /* Check to see if the register banks are changing */
3115 if(PCI(pc)->isModReg) {
3117 pCodeOp *pcop = PCI(pc)->pcop;
3118 switch(PCI(pc)->op) {
3120 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3121 fprintf(stderr, " FillFlow - Set RP0\n");
3122 //outCond |= PCC_REG_BANK1;
3123 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3124 fprintf(stderr, " FillFlow - Set RP1\n");
3125 //outCond |= PCC_REG_BANK3;
3129 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3130 fprintf(stderr, " FillFlow - Clr RP0\n");
3131 //outCond |= PCC_REG_BANK1;
3132 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3133 fprintf(stderr, " FillFlow - Clr RP1\n");
3134 //outCond |= PCC_REG_BANK3;
3138 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3139 genericPrint(stderr, pc);
3144 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3148 pcflow->inCond |= (inCond & ~pcflow->outCond);
3149 pcflow->outCond |= outCond;
3154 pc = findNextpCode(pc->next, PC_OPCODE);
3155 } while (pc && (pc != pcflow->end));
3159 fprintf(stderr, " FillFlow - Bad end of flow\n");
3162 fprintf(stderr, " FillFlow inCond: ");
3163 dumpCond(pcflow->inCond);
3164 fprintf(stderr, " FillFlow outCond: ");
3165 dumpCond(pcflow->outCond);
3168 /*-----------------------------------------------------------------*/
3169 /*-----------------------------------------------------------------*/
3170 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3173 if(!from || !to || !to->pcflow || !from->pcflow)
3176 addSet(&(from->pcflow->to), to->pcflow);
3177 addSet(&(to->pcflow->from), from->pcflow);
3181 /*-----------------------------------------------------------------*/
3182 /*-----------------------------------------------------------------*/
3183 void LinkFlow(pBlock *pb)
3190 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3191 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3192 pcflow = pcflow->next) {
3195 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3197 //FillFlow(PCFL(pcflow));
3199 pc = PCFL(pcflow)->end;
3201 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3202 if(isPCI_SKIP(pc)) {
3203 //fprintf(stderr, "ends with skip\n");
3204 pct=findNextInstruction(pc->next);
3205 LinkFlow_pCode(PCI(pc),PCI(pct));
3206 pct=findNextInstruction(pct->next);
3207 LinkFlow_pCode(PCI(pc),PCI(pct));
3211 if(isPCI_BRANCH(pc)) {
3212 //fprintf(stderr, "ends with branch\n");
3218 fprintf(stderr, "has an unrecognized ending:\n");
3219 pc->print(stderr,pc);
3222 fprintf(stderr, "has no end pcode\n");
3227 /*-----------------------------------------------------------------*/
3228 /*-----------------------------------------------------------------*/
3229 int OptimizepBlock(pBlock *pb)
3234 if(!pb || !peepOptimizing)
3237 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3238 for(pc = pb->pcHead; pc; pc = pc->next)
3239 matches += pCodePeepMatchRule(pc);
3241 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3246 /*-----------------------------------------------------------------*/
3247 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3248 /*-----------------------------------------------------------------*/
3249 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3253 for(pc = pcs; pc; pc = pc->next) {
3255 if((pc->type == PC_OPCODE) &&
3257 (PCI(pc)->pcop->type == PO_LABEL) &&
3258 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3266 /*-----------------------------------------------------------------*/
3267 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3268 /* pCode chain if they're not used. */
3269 /*-----------------------------------------------------------------*/
3270 void pBlockRemoveUnusedLabels(pBlock *pb)
3272 pCode *pc; pCodeLabel *pcl;
3277 for(pc = pb->pcHead; pc; pc = pc->next) {
3279 if(pc->type == PC_LABEL)
3281 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3282 pcl = PCL(PCI(pc)->label->pc);
3285 /* This pCode is a label, so search the pBlock to see if anyone
3288 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3289 /* Couldn't find an instruction that refers to this label
3290 * So, unlink the pCode label from it's pCode chain
3291 * and destroy the label */
3293 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3295 if(pc->type == PC_LABEL) {
3297 pCodeLabelDestruct(pc);
3299 unlinkpCodeFromBranch(pc, PCODE(pcl));
3300 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3311 /*-----------------------------------------------------------------*/
3312 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3313 /* chain and put them into pBranches that are */
3314 /* associated with the appropriate pCode */
3316 /*-----------------------------------------------------------------*/
3317 void pBlockMergeLabels(pBlock *pb)
3320 pCode *pc, *pcnext=NULL;
3325 /* First, Try to remove any unused labels */
3326 //pBlockRemoveUnusedLabels(pb);
3328 /* Now loop through the pBlock and merge the labels with the opcodes */
3330 for(pc = pb->pcHead; pc; pc = pc->next) {
3332 if(pc->type == PC_LABEL) {
3333 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3334 if( !(pcnext = findNextInstruction(pc)) )
3335 return; // Couldn't find an instruction associated with this label
3337 // Unlink the pCode label from it's pCode chain
3340 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3341 // And link it into the instruction's pBranch labels. (Note, since
3342 // it's possible to have multiple labels associated with one instruction
3343 // we must provide a means to accomodate the additional labels. Thus
3344 // the labels are placed into the singly-linked list "label" as
3345 // opposed to being a single member of the pCodeInstruction.)
3347 //_ALLOC(pbr,sizeof(pBranch));
3348 pbr = Safe_calloc(1,sizeof(pBranch));
3352 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3360 pBlockRemoveUnusedLabels(pb);
3364 /*-----------------------------------------------------------------*/
3365 /*-----------------------------------------------------------------*/
3366 void OptimizepCode(char dbName)
3368 #define MAX_PASSES 4
3377 DFPRINTF((stderr," Optimizing pCode\n"));
3380 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3381 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3382 matches += OptimizepBlock(pb);
3385 while(matches && ++passes < MAX_PASSES);
3389 /*-----------------------------------------------------------------*/
3390 /* popCopyGPR2Bit - copy a pcode operator */
3391 /*-----------------------------------------------------------------*/
3393 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3397 pcop = newpCodeOpBit(pc->name, bitval, 0);
3399 if( !( (pcop->type == PO_LABEL) ||
3400 (pcop->type == PO_LITERAL) ||
3401 (pcop->type == PO_STR) ))
3402 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3410 /*-----------------------------------------------------------------*/
3411 /*-----------------------------------------------------------------*/
3412 int InstructionRegBank(pCode *pc)
3416 if( (reg = getRegFromInstruction(pc)) == NULL)
3419 return REG_BANK(reg);
3424 /*-----------------------------------------------------------------*/
3425 /*-----------------------------------------------------------------*/
3426 void FixRegisterBanking(pBlock *pb)
3438 pc = findNextpCode(pb->pcHead, PC_FLOW);
3441 /* loop through all of the flow blocks with in one pblock */
3443 //fprintf(stderr,"Register banking\n");
3446 /* at this point, pc should point to a PC_FLOW object */
3449 /* for each flow block, determine the register banking
3454 //genericPrint(stderr, pc);
3456 reg = getRegFromInstruction(pc);
3459 fprintf(stderr, " %s ",reg->name);
3460 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3464 if(reg && REG_BANK(reg)!=cur_bank) {
3465 /* Examine the instruction before this one to make sure it is
3466 * not a skip type instruction */
3467 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3468 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3469 int b = cur_bank ^ REG_BANK(reg);
3471 //fprintf(stderr, "Cool! can switch banks\n");
3472 cur_bank = REG_BANK(reg);
3474 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3475 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3476 pCodeInsertAfter(pc->prev, new_pc);
3477 if(PCI(pc)->label) {
3478 PCI(new_pc)->label = PCI(pc)->label;
3479 PCI(pc)->label = NULL;
3482 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3483 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3484 pCodeInsertAfter(pc, new_pc);
3490 //fprintf(stderr, "Bummer can't switch banks\n");
3498 } while(pc && !(isPCFL(pc)));
3500 if(pcprev && cur_bank) {
3501 /* Brute force - make sure that we point to bank 0 at the
3502 * end of each flow block */
3503 new_pc = newpCode(POC_BCF,
3504 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3505 pCodeInsertAfter(pcprev, new_pc);
3513 void pBlockDestruct(pBlock *pb)
3524 /*-----------------------------------------------------------------*/
3525 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3526 /* name dbName and combine them */
3527 /* into one block */
3528 /*-----------------------------------------------------------------*/
3529 void mergepBlocks(char dbName)
3532 pBlock *pb, *pbmerged = NULL,*pbn;
3534 pb = the_pFile->pbHead;
3536 //fprintf(stderr," merging blocks named %c\n",dbName);
3540 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3541 if( getpBlock_dbName(pb) == dbName) {
3543 //fprintf(stderr," merged block %c\n",dbName);
3548 addpCode2pBlock(pbmerged, pb->pcHead);
3549 /* addpCode2pBlock doesn't handle the tail: */
3550 pbmerged->pcTail = pb->pcTail;
3552 pb->prev->next = pbn;
3554 pbn->prev = pb->prev;
3559 //printpBlock(stderr, pbmerged);
3566 /*-----------------------------------------------------------------*/
3567 /* AnalyzeBanking - Called after the memory addresses have been */
3568 /* assigned to the registers. */
3570 /*-----------------------------------------------------------------*/
3571 void AnalyzeBanking(void)
3580 /* Phase 2 - Flow Analysis
3582 * In this phase, the pCode is partition into pCodeFlow
3583 * blocks. The flow blocks mark the points where a continuous
3584 * stream of instructions changes flow (e.g. because of
3585 * a call or goto or whatever).
3588 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3591 /* Phase 2 - Flow Analysis - linking flow blocks
3593 * In this phase, the individual flow blocks are examined
3594 * to determine their order of excution.
3597 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3600 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3601 FixRegisterBanking(pb);
3604 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3606 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3607 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3608 pcflow = pcflow->next) {
3610 FillFlow(PCFL(pcflow));
3617 /*-----------------------------------------------------------------*/
3618 /* buildCallTree - look at the flow and extract all of the calls */
3620 /*-----------------------------------------------------------------*/
3621 set *register_usage(pBlock *pb);
3623 void buildCallTree(void )
3634 /* Now build the call tree.
3635 First we examine all of the pCodes for functions.
3636 Keep in mind that the function boundaries coincide
3637 with pBlock boundaries.
3639 The algorithm goes something like this:
3640 We have two nested loops. The outer loop iterates
3641 through all of the pBlocks/functions. The inner
3642 loop iterates through all of the pCodes for
3643 a given pBlock. When we begin iterating through
3644 a pBlock, the variable pc_fstart, pCode of the start
3645 of a function, is cleared. We then search for pCodes
3646 of type PC_FUNCTION. When one is encountered, we
3647 initialize pc_fstart to this and at the same time
3648 associate a new pBranch object that signifies a
3649 branch entry. If a return is found, then this signifies
3650 a function exit point. We'll link the pCodes of these
3651 returns to the matching pc_fstart.
3653 When we're done, a doubly linked list of pBranches
3654 will exist. The head of this list is stored in
3655 `the_pFile', which is the meta structure for all
3656 of the pCode. Look at the printCallTree function
3657 on how the pBranches are linked together.
3660 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3661 pCode *pc_fstart=NULL;
3662 for(pc = pb->pcHead; pc; pc = pc->next) {
3663 if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
3664 if (PCF(pc)->fname) {
3666 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3667 //fprintf(stderr," found main \n");
3668 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3672 //_ALLOC(pbr,sizeof(pBranch));
3673 pbr = Safe_calloc(1,sizeof(pBranch));
3674 pbr->pc = pc_fstart = pc;
3677 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3679 // Here's a better way of doing the same:
3680 addSet(&pb->function_entries, pc);
3683 // Found an exit point in a function, e.g. return
3684 // (Note, there may be more than one return per function)
3686 pBranchLink(PCF(pc_fstart), PCF(pc));
3688 addSet(&pb->function_exits, pc);
3690 } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3691 addSet(&pb->function_calls,pc);
3696 /* Re-allocate the registers so that there are no collisions
3697 * between local variables when one function call another */
3699 pic14_deallocateAllRegs();
3701 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3708 /*-----------------------------------------------------------------*/
3709 /* AnalyzepCode - parse the pCode that has been generated and form */
3710 /* all of the logical connections. */
3712 /* Essentially what's done here is that the pCode flow is */
3714 /*-----------------------------------------------------------------*/
3716 void AnalyzepCode(char dbName)
3727 /* Phase 1 - Register allocation and peep hole optimization
3729 * The first part of the analysis is to determine the registers
3730 * that are used in the pCode. Once that is done, the peep rules
3731 * are applied to the code. We continue to loop until no more
3732 * peep rule optimizations are found (or until we exceed the
3733 * MAX_PASSES threshold).
3735 * When done, the required registers will be determined.
3741 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3743 /* First, merge the labels with the instructions */
3744 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3745 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3747 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3748 //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3749 pBlockMergeLabels(pb);
3756 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3757 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3758 changes += OptimizepBlock(pb);
3761 } while(changes && (i++ < MAX_PASSES));
3766 /*-----------------------------------------------------------------*/
3767 /* ispCodeFunction - returns true if *pc is the pCode of a */
3769 /*-----------------------------------------------------------------*/
3770 bool ispCodeFunction(pCode *pc)
3773 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3779 /*-----------------------------------------------------------------*/
3780 /* findFunction - Search for a function by name (given the name) */
3781 /* in the set of all functions that are in a pBlock */
3782 /* (note - I expect this to change because I'm planning to limit */
3783 /* pBlock's to just one function declaration */
3784 /*-----------------------------------------------------------------*/
3785 pCode *findFunction(char *fname)
3792 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3794 pc = setFirstItem(pb->function_entries);
3797 if((pc->type == PC_FUNCTION) &&
3799 (strcmp(fname, PCF(pc)->fname)==0))
3802 pc = setNextItem(pb->function_entries);
3810 void MarkUsedRegisters(set *regset)
3815 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3816 r2 = pic14_regWithIdx(r1->rIdx);
3822 void pBlockStats(FILE *of, pBlock *pb)
3828 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3830 // for now just print the first element of each set
3831 pc = setFirstItem(pb->function_entries);
3833 fprintf(of,";entry: ");
3836 pc = setFirstItem(pb->function_exits);
3838 fprintf(of,";has an exit\n");
3842 pc = setFirstItem(pb->function_calls);
3844 fprintf(of,";functions called:\n");
3847 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3848 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
3850 pc = setNextItem(pb->function_calls);
3854 r = setFirstItem(pb->tregisters);
3856 int n = elementsInSet(pb->tregisters);
3858 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3861 fprintf(of,"; %s\n",r->name);
3862 r = setNextItem(pb->tregisters);
3867 /*-----------------------------------------------------------------*/
3868 /*-----------------------------------------------------------------*/
3869 static void sequencepCode(void)
3875 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3877 pb->seq = GpCodeSequenceNumber+1;
3879 for( pc = pb->pcHead; pc; pc = pc->next)
3880 pc->seq = ++GpCodeSequenceNumber;
3885 /*-----------------------------------------------------------------*/
3886 /*-----------------------------------------------------------------*/
3887 set *register_usage(pBlock *pb)
3890 set *registers=NULL;
3891 set *registersInCallPath = NULL;
3893 /* check recursion */
3895 pc = setFirstItem(pb->function_entries);
3902 if(pc->type != PC_FUNCTION)
3903 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3905 pc = setFirstItem(pb->function_calls);
3906 for( ; pc; pc = setNextItem(pb->function_calls)) {
3908 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3909 char *dest = get_op_from_instruction(PCI(pc));
3911 pcn = findFunction(dest);
3913 registersInCallPath = register_usage(pcn->pb);
3915 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3920 pBlockStats(stderr,pb); // debug
3923 // Mark the registers in this block as used.
3925 MarkUsedRegisters(pb->tregisters);
3926 if(registersInCallPath) {
3927 /* registers were used in the functions this pBlock has called */
3928 /* so now, we need to see if these collide with the ones we are */
3931 regs *r1,*r2, *newreg;
3933 DFPRINTF((stderr,"comparing registers\n"));
3935 r1 = setFirstItem(registersInCallPath);
3938 r2 = setFirstItem(pb->tregisters);
3940 while(r2 && (r1->type != REG_STK)) {
3942 if(r2->rIdx == r1->rIdx) {
3943 newreg = pic14_findFreeReg(REG_GPR);
3947 DFPRINTF((stderr,"Bummer, no more registers.\n"));
3951 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3952 r1->rIdx, newreg->rIdx));
3953 r2->rIdx = newreg->rIdx;
3954 //if(r2->name) free(r2->name);
3956 r2->name = Safe_strdup(newreg->name);
3960 newreg->wasUsed = 1;
3962 r2 = setNextItem(pb->tregisters);
3965 r1 = setNextItem(registersInCallPath);
3968 /* Collisions have been resolved. Now free the registers in the call path */
3969 r1 = setFirstItem(registersInCallPath);
3971 if(r1->type != REG_STK) {
3972 newreg = pic14_regWithIdx(r1->rIdx);
3975 r1 = setNextItem(registersInCallPath);
3979 // MarkUsedRegisters(pb->registers);
3981 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3984 DFPRINTF((stderr,"returning regs\n"));
3986 DFPRINTF((stderr,"not returning regs\n"));
3988 DFPRINTF((stderr,"pBlock after register optim.\n"));
3989 pBlockStats(stderr,pb); // debug
3995 /*-----------------------------------------------------------------*/
3996 /* printCallTree - writes the call tree to a file */
3998 /*-----------------------------------------------------------------*/
3999 void pct2(FILE *of,pBlock *pb,int indent)
4003 // set *registersInCallPath = NULL;
4006 return;// registers;
4009 return; // registers; //recursion ?
4011 pc = setFirstItem(pb->function_entries);
4018 for(i=0;i<indent;i++) // Indentation
4021 if(pc->type == PC_FUNCTION)
4022 fprintf(of,"%s\n",PCF(pc)->fname);
4027 pc = setFirstItem(pb->function_calls);
4028 for( ; pc; pc = setNextItem(pb->function_calls)) {
4030 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4031 char *dest = get_op_from_instruction(PCI(pc));
4033 pcn = findFunction(dest);
4035 pct2(of,pcn->pb,indent+1);
4037 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4045 fprintf(stderr,"pBlock before register optim.\n");
4046 pBlockStats(stderr,pb); // debug
4048 if(registersInCallPath) {
4049 /* registers were used in the functions this pBlock has called */
4050 /* so now, we need to see if these collide with the ones we are using here */
4052 regs *r1,*r2, *newreg;
4054 fprintf(stderr,"comparing registers\n");
4056 r1 = setFirstItem(registersInCallPath);
4059 r2 = setFirstItem(pb->registers);
4063 if(r2->rIdx == r1->rIdx) {
4064 newreg = pic14_findFreeReg();
4068 fprintf(stderr,"Bummer, no more registers.\n");
4072 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
4073 r1->rIdx, newreg->rIdx);
4074 r2->rIdx = newreg->rIdx;
4075 //if(r2->name) free(r2->name);
4077 r2->name = Safe_strdup(newreg->name);
4081 newreg->wasUsed = 1;
4083 r2 = setNextItem(pb->registers);
4086 r1 = setNextItem(registersInCallPath);
4089 /* Collisions have been resolved. Now free the registers in the call path */
4090 r1 = setFirstItem(registersInCallPath);
4092 newreg = pic14_regWithIdx(r1->rIdx);
4094 r1 = setNextItem(registersInCallPath);
4098 MarkUsedRegisters(pb->registers);
4100 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
4103 fprintf(stderr,"returning regs\n");
4105 fprintf(stderr,"not returning regs\n");
4107 fprintf(stderr,"pBlock after register optim.\n");
4108 pBlockStats(stderr,pb); // debug
4116 /*-----------------------------------------------------------------*/
4117 /* printCallTree - writes the call tree to a file */
4119 /*-----------------------------------------------------------------*/
4121 void printCallTree(FILE *of)
4133 fprintf(of, "\npBlock statistics\n");
4134 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4139 fprintf(of,"Call Tree\n");
4140 pbr = the_pFile->functions;
4144 if(!ispCodeFunction(pc))
4145 fprintf(of,"bug in call tree");
4148 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4150 while(pc->next && !ispCodeFunction(pc->next)) {
4152 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4153 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
4161 /* Re-allocate the registers so that there are no collisions
4162 * between local variables when one function call another */
4164 pic14_deallocateAllRegs();
4166 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4172 fprintf(of,"\n**************\n\na better call tree\n");
4173 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4178 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4179 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));