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 = 0;
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( pCodeInstruction *pcc);
105 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
106 int pCodePeepMatchRule(pCode *pc);
107 void pBlockStats(FILE *of, pBlock *pb);
108 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
110 pCodeInstruction pciADDWF = {
111 {PC_OPCODE, NULL, NULL, 0, NULL,
123 1,0, // dest, bit instruction
126 (PCC_W | PCC_REGISTER), // inCond
127 (PCC_REGISTER | PCC_Z) // outCond
130 pCodeInstruction pciADDFW = {
131 {PC_OPCODE, NULL, NULL, 0, NULL,
143 0,0, // dest, bit instruction
146 (PCC_W | PCC_REGISTER), // inCond
147 (PCC_W | PCC_Z) // outCond
150 pCodeInstruction pciADDLW = {
151 {PC_OPCODE, NULL, NULL, 0, NULL,
163 0,0, // dest, bit instruction
167 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
170 pCodeInstruction pciANDLW = {
171 {PC_OPCODE, NULL, NULL, 0, NULL,
183 0,0, // dest, bit instruction
187 (PCC_W | PCC_Z) // outCond
190 pCodeInstruction pciANDWF = {
191 {PC_OPCODE, NULL, NULL, 0, NULL,
203 1,0, // dest, bit instruction
206 (PCC_W | PCC_REGISTER), // inCond
207 (PCC_REGISTER | PCC_Z) // outCond
210 pCodeInstruction pciANDFW = {
211 {PC_OPCODE, NULL, NULL, 0, NULL,
223 0,0, // dest, bit instruction
226 (PCC_W | PCC_REGISTER), // inCond
227 (PCC_W | PCC_Z) // outCond
230 pCodeInstruction pciBCF = {
231 {PC_OPCODE, NULL, NULL, 0, NULL,
243 1,1, // dest, bit instruction
246 PCC_REGISTER, // inCond
247 PCC_REGISTER // outCond
250 pCodeInstruction pciBSF = {
251 {PC_OPCODE, NULL, NULL, 0, NULL,
263 1,1, // dest, bit instruction
266 PCC_REGISTER, // inCond
267 PCC_REGISTER // outCond
270 pCodeInstruction pciBTFSC = {
271 {PC_OPCODE, NULL, NULL, 0, NULL,
283 0,1, // dest, bit instruction
286 PCC_REGISTER, // inCond
290 pCodeInstruction pciBTFSS = {
291 {PC_OPCODE, NULL, NULL, 0, NULL,
303 0,1, // dest, bit instruction
306 PCC_REGISTER, // inCond
310 pCodeInstruction pciCALL = {
311 {PC_OPCODE, NULL, NULL, 0, NULL,
323 0,0, // dest, bit instruction
330 pCodeInstruction pciCOMF = {
331 {PC_OPCODE, NULL, NULL, 0, NULL,
343 1,0, // dest, bit instruction
346 PCC_REGISTER, // inCond
347 PCC_REGISTER // outCond
350 pCodeInstruction pciCOMFW = {
351 {PC_OPCODE, NULL, NULL, 0, NULL,
363 0,0, // dest, bit instruction
366 PCC_REGISTER, // inCond
370 pCodeInstruction pciCLRF = {
371 {PC_OPCODE, NULL, NULL, 0, NULL,
383 0,0, // dest, bit instruction
386 PCC_REGISTER, // inCond
387 PCC_REGISTER // outCond
390 pCodeInstruction pciCLRW = {
391 {PC_OPCODE, NULL, NULL, 0, NULL,
403 0,0, // dest, bit instruction
410 pCodeInstruction pciDECF = {
411 {PC_OPCODE, NULL, NULL, 0, NULL,
423 1,0, // dest, bit instruction
426 PCC_REGISTER, // inCond
427 PCC_REGISTER // outCond
430 pCodeInstruction pciDECFW = {
431 {PC_OPCODE, NULL, NULL, 0, NULL,
443 0,0, // dest, bit instruction
446 PCC_REGISTER, // inCond
450 pCodeInstruction pciDECFSZ = {
451 {PC_OPCODE, NULL, NULL, 0, NULL,
463 1,0, // dest, bit instruction
466 PCC_REGISTER, // inCond
467 PCC_REGISTER // outCond
470 pCodeInstruction pciDECFSZW = {
471 {PC_OPCODE, NULL, NULL, 0, NULL,
483 0,0, // dest, bit instruction
486 PCC_REGISTER, // inCond
490 pCodeInstruction pciGOTO = {
491 {PC_OPCODE, NULL, NULL, 0, NULL,
503 0,0, // dest, bit instruction
510 pCodeInstruction pciINCF = {
511 {PC_OPCODE, NULL, NULL, 0, NULL,
523 1,0, // dest, bit instruction
526 PCC_REGISTER, // inCond
527 PCC_REGISTER // outCond
530 pCodeInstruction pciINCFW = {
531 {PC_OPCODE, NULL, NULL, 0, NULL,
543 0,0, // dest, bit instruction
546 PCC_REGISTER, // inCond
550 pCodeInstruction pciINCFSZ = {
551 {PC_OPCODE, NULL, NULL, 0, NULL,
563 1,0, // dest, bit instruction
566 PCC_REGISTER, // inCond
567 PCC_REGISTER // outCond
570 pCodeInstruction pciINCFSZW = {
571 {PC_OPCODE, NULL, NULL, 0, NULL,
583 0,0, // dest, bit instruction
586 PCC_REGISTER, // inCond
590 pCodeInstruction pciIORWF = {
591 {PC_OPCODE, NULL, NULL, 0, NULL,
603 1,0, // dest, bit instruction
606 (PCC_W | PCC_REGISTER), // inCond
607 (PCC_REGISTER | PCC_Z) // outCond
610 pCodeInstruction pciIORFW = {
611 {PC_OPCODE, NULL, NULL, 0, NULL,
623 0,0, // dest, bit instruction
626 (PCC_W | PCC_REGISTER), // inCond
627 (PCC_W | PCC_Z) // outCond
630 pCodeInstruction pciIORLW = {
631 {PC_OPCODE, NULL, NULL, 0, NULL,
643 0,0, // dest, bit instruction
647 (PCC_W | PCC_Z) // outCond
650 pCodeInstruction pciMOVF = {
651 {PC_OPCODE, NULL, NULL, 0, NULL,
663 1,0, // dest, bit instruction
666 PCC_REGISTER, // inCond
670 pCodeInstruction pciMOVFW = {
671 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,0, // dest, bit instruction
686 PCC_REGISTER, // inCond
687 (PCC_W | PCC_Z) // outCond
690 pCodeInstruction pciMOVWF = {
691 {PC_OPCODE, NULL, NULL, 0, NULL,
703 0,0, // dest, bit instruction
707 PCC_REGISTER // outCond
710 pCodeInstruction pciMOVLW = {
711 {PC_OPCODE, NULL, NULL, 0, NULL,
723 0,0, // dest, bit instruction
730 pCodeInstruction pciNOP = {
731 {PC_OPCODE, NULL, NULL, 0, NULL,
742 0,0, // dest, bit instruction
749 pCodeInstruction pciRETFIE = {
750 {PC_OPCODE, NULL, NULL, 0, NULL,
762 0,0, // dest, bit instruction
766 PCC_NONE // outCond (not true... affects the GIE bit too)
769 pCodeInstruction pciRETLW = {
770 {PC_OPCODE, NULL, NULL, 0, NULL,
782 0,0, // dest, bit instruction
789 pCodeInstruction pciRETURN = {
790 {PC_OPCODE, NULL, NULL, 0, NULL,
802 0,0, // dest, bit instruction
809 pCodeInstruction pciRLF = {
810 {PC_OPCODE, NULL, NULL, 0, NULL,
822 1,0, // dest, bit instruction
825 (PCC_C | PCC_REGISTER), // inCond
826 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
829 pCodeInstruction pciRLFW = {
830 {PC_OPCODE, NULL, NULL, 0, NULL,
842 0,0, // dest, bit instruction
845 (PCC_C | PCC_REGISTER), // inCond
846 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
849 pCodeInstruction pciRRF = {
850 {PC_OPCODE, NULL, NULL, 0, NULL,
862 1,0, // dest, bit instruction
865 (PCC_C | PCC_REGISTER), // inCond
866 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
869 pCodeInstruction pciRRFW = {
870 {PC_OPCODE, NULL, NULL, 0, NULL,
882 0,0, // dest, bit instruction
885 (PCC_C | PCC_REGISTER), // inCond
886 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
889 pCodeInstruction pciSUBWF = {
890 {PC_OPCODE, NULL, NULL, 0, NULL,
902 1,0, // dest, bit instruction
905 (PCC_W | PCC_REGISTER), // inCond
906 (PCC_REGISTER | PCC_Z) // outCond
909 pCodeInstruction pciSUBFW = {
910 {PC_OPCODE, NULL, NULL, 0, NULL,
922 0,0, // dest, bit instruction
925 (PCC_W | PCC_REGISTER), // inCond
926 (PCC_W | PCC_Z) // outCond
929 pCodeInstruction pciSUBLW = {
930 {PC_OPCODE, NULL, NULL, 0, NULL,
942 0,0, // dest, bit instruction
946 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
949 pCodeInstruction pciSWAPF = {
950 {PC_OPCODE, NULL, NULL, 0, NULL,
962 1,0, // dest, bit instruction
965 (PCC_REGISTER), // inCond
966 (PCC_REGISTER) // outCond
969 pCodeInstruction pciSWAPFW = {
970 {PC_OPCODE, NULL, NULL, 0, NULL,
982 0,0, // dest, bit instruction
985 (PCC_REGISTER), // inCond
989 pCodeInstruction pciTRIS = {
990 {PC_OPCODE, NULL, NULL, 0, NULL,
1002 0,0, // dest, bit instruction
1003 0,0, // branch, skip
1006 PCC_REGISTER // outCond
1009 pCodeInstruction pciXORWF = {
1010 {PC_OPCODE, NULL, NULL, 0, NULL,
1016 NULL, // from branch
1022 1,0, // dest, bit instruction
1023 0,0, // branch, skip
1025 (PCC_W | PCC_REGISTER), // inCond
1026 (PCC_REGISTER | PCC_Z) // outCond
1029 pCodeInstruction pciXORFW = {
1030 {PC_OPCODE, NULL, NULL, 0, NULL,
1036 NULL, // from branch
1042 0,0, // dest, bit instruction
1043 0,0, // branch, skip
1045 (PCC_W | PCC_REGISTER), // inCond
1046 (PCC_W | PCC_Z) // outCond
1049 pCodeInstruction pciXORLW = {
1050 {PC_OPCODE, NULL, NULL, 0, NULL,
1056 NULL, // from branch
1062 0,0, // dest, bit instruction
1063 0,0, // branch, skip
1066 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1070 #define MAX_PIC14MNEMONICS 100
1071 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1073 /* This definition needs to be part of configure.in */
1074 // #define USE_VSNPRINTF
1076 #ifdef USE_VSNPRINTF
1077 // Alas, vsnprintf is not ANSI standard, and does not exist
1078 // on Solaris (and probably other non-Gnu flavored Unixes).
1080 /*-----------------------------------------------------------------*/
1081 /* SAFE_snprintf - like snprintf except the string pointer is */
1082 /* after the string has been printed to. This is */
1083 /* useful for printing to string as though if it */
1084 /* were a stream. */
1085 /*-----------------------------------------------------------------*/
1086 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1094 va_start(val, format);
1096 vsnprintf(*str, *size, format, val);
1102 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1110 #else // USE_VSNPRINTF
1112 // This version is *not* safe, despite the name.
1114 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1118 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1123 va_start(val, format);
1125 vsprintf(buffer, format, val);
1128 len = strlen(buffer);
1130 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1133 strcpy(*str, buffer);
1139 #endif // USE_VSNPRINTF
1142 extern void initStack(int base_address, int size);
1143 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1144 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1145 extern void init_pic(char *);
1147 void pCodeInitRegisters(void)
1151 init_pic(port->processor);
1153 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1154 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1155 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1156 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1157 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1158 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1160 pc_status.rIdx = IDX_STATUS;
1161 pc_fsr.rIdx = IDX_FSR;
1162 pc_indf.rIdx = IDX_INDF;
1163 pc_intcon.rIdx = IDX_INTCON;
1164 pc_pcl.rIdx = IDX_PCL;
1165 pc_pclath.rIdx = IDX_PCLATH;
1167 pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1168 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1169 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1171 pc_kzero.rIdx = IDX_KZ;
1172 pc_wsave.rIdx = IDX_WSAVE;
1173 pc_ssave.rIdx = IDX_SSAVE;
1177 /*-----------------------------------------------------------------*/
1178 /* mnem2key - convert a pic mnemonic into a hash key */
1179 /* (BTW - this spreads the mnemonics quite well) */
1181 /*-----------------------------------------------------------------*/
1183 int mnem2key(char const *mnem)
1192 key += toupper(*mnem++) +1;
1196 return (key & 0x1f);
1200 void pic14initMnemonics(void)
1205 pCodeInstruction *pci;
1207 if(mnemonics_initialized)
1210 //FIXME - probably should NULL out the array before making the assignments
1211 //since we check the array contents below this initialization.
1213 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1214 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1215 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1216 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1217 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1218 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1219 pic14Mnemonics[POC_BCF] = &pciBCF;
1220 pic14Mnemonics[POC_BSF] = &pciBSF;
1221 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1222 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1223 pic14Mnemonics[POC_CALL] = &pciCALL;
1224 pic14Mnemonics[POC_COMF] = &pciCOMF;
1225 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1226 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1227 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1228 pic14Mnemonics[POC_DECF] = &pciDECF;
1229 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1230 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1231 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1232 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1233 pic14Mnemonics[POC_INCF] = &pciINCF;
1234 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1235 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1236 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1237 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1238 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1239 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1240 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1241 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1242 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1243 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1244 pic14Mnemonics[POC_NOP] = &pciNOP;
1245 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1246 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1247 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1248 pic14Mnemonics[POC_RLF] = &pciRLF;
1249 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1250 pic14Mnemonics[POC_RRF] = &pciRRF;
1251 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1252 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1253 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1254 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1255 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1256 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1257 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1258 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1259 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1260 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1262 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1263 if(pic14Mnemonics[i])
1264 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1265 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1268 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1269 pci = hTabNextItem(pic14MnemonicsHash, &key);
1272 mnemonics_initialized = 1;
1275 int getpCodePeepCommand(char *cmd);
1277 int getpCode(char *mnem,unsigned dest)
1280 pCodeInstruction *pci;
1281 int key = mnem2key(mnem);
1283 if(!mnemonics_initialized)
1284 pic14initMnemonics();
1286 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1290 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1291 if((pci->num_ops <= 1) || (pci->isModReg == dest))
1295 pci = hTabNextItemWK (pic14MnemonicsHash);
1302 /*-----------------------------------------------------------------*
1303 * pic14initpCodePeepCommands
1305 *-----------------------------------------------------------------*/
1306 void pic14initpCodePeepCommands(void)
1314 hTabAddItem(&pic14pCodePeepCommandsHash,
1315 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1317 } while (peepCommands[i].cmd);
1319 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1322 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1323 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1328 /*-----------------------------------------------------------------
1331 *-----------------------------------------------------------------*/
1333 int getpCodePeepCommand(char *cmd)
1337 int key = mnem2key(cmd);
1340 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1343 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1344 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1348 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1355 char getpBlock_dbName(pBlock *pb)
1361 return pb->cmemmap->dbName;
1365 void pBlockConvert2ISR(pBlock *pb)
1376 /*-----------------------------------------------------------------*/
1377 /* movepBlock2Head - given the dbname of a pBlock, move all */
1378 /* instances to the front of the doubly linked */
1379 /* list of pBlocks */
1380 /*-----------------------------------------------------------------*/
1382 void movepBlock2Head(char dbName)
1386 pb = the_pFile->pbHead;
1390 if(getpBlock_dbName(pb) == dbName) {
1391 pBlock *pbn = pb->next;
1392 pb->next = the_pFile->pbHead;
1393 the_pFile->pbHead->prev = pb;
1394 the_pFile->pbHead = pb;
1397 pb->prev->next = pbn;
1399 // If the pBlock that we just moved was the last
1400 // one in the link of all of the pBlocks, then we
1401 // need to point the tail to the block just before
1402 // the one we moved.
1403 // Note: if pb->next is NULL, then pb must have
1404 // been the last pBlock in the chain.
1407 pbn->prev = pb->prev;
1409 the_pFile->pbTail = pb->prev;
1420 void copypCode(FILE *of, char dbName)
1424 if(!of || !the_pFile)
1427 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1428 if(getpBlock_dbName(pb) == dbName) {
1435 void pcode_test(void)
1438 DFPRINTF((stderr,"pcode is alive!\n"));
1448 /* create the file name */
1449 strcpy(buffer,srcFileName);
1450 strcat(buffer,".p");
1452 if( !(pFile = fopen(buffer, "w" ))) {
1453 werror(E_FILE_OPEN_ERR,buffer);
1457 fprintf(pFile,"pcode dump\n\n");
1459 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1460 fprintf(pFile,"\n\tNew pBlock\n\n");
1462 fprintf(pFile,"%s",pb->cmemmap->sname);
1464 fprintf(pFile,"internal pblock");
1466 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1467 printpBlock(pFile,pb);
1471 /*-----------------------------------------------------------------*/
1472 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1473 /* ister, RegCond will return the bit being referenced. */
1475 /* fixme - why not just OR in the pcop bit field */
1476 /*-----------------------------------------------------------------*/
1478 static int RegCond(pCodeOp *pcop)
1484 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1485 switch(PCORB(pcop)->bit) {
1499 /*-----------------------------------------------------------------*/
1500 /* newpCode - create and return a newly initialized pCode */
1502 /* fixme - rename this */
1504 /* The purpose of this routine is to create a new Instruction */
1505 /* pCode. This is called by gen.c while the assembly code is being */
1509 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1510 /* (note that the op is analogous to but not the */
1511 /* same thing as the opcode of the instruction.) */
1512 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1515 /* a pointer to the new malloc'd pCode is returned. */
1519 /*-----------------------------------------------------------------*/
1520 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1522 pCodeInstruction *pci ;
1524 if(!mnemonics_initialized)
1525 pic14initMnemonics();
1527 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1529 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1530 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1533 if(pci->inCond == PCC_EXAMINE_PCOP)
1534 pci->inCond = RegCond(pcop);
1536 if(pci->outCond == PCC_EXAMINE_PCOP)
1537 pci->outCond = RegCond(pcop);
1539 pci->pc.prev = pci->pc.next = NULL;
1540 return (pCode *)pci;
1543 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1549 /*-----------------------------------------------------------------*/
1550 /* newpCodeWild - create a "wild" as in wild card pCode */
1552 /* Wild pcodes are used during the peep hole optimizer to serve */
1553 /* as place holders for any instruction. When a snippet of code is */
1554 /* compared to a peep hole rule, the wild card opcode will match */
1555 /* any instruction. However, the optional operand and label are */
1556 /* additional qualifiers that must also be matched before the */
1557 /* line (of assembly code) is declared matched. Note that the */
1558 /* operand may be wild too. */
1560 /* Note, a wild instruction is specified just like a wild var: */
1561 /* %4 ; A wild instruction, */
1562 /* See the peeph.def file for additional examples */
1564 /*-----------------------------------------------------------------*/
1566 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1571 pcw = Safe_calloc(1,sizeof(pCodeWild));
1573 pcw->pci.pc.type = PC_WILD;
1574 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1575 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1576 pcw->pci.pc.pb = NULL;
1578 // pcw->pci.pc.analyze = genericAnalyze;
1579 pcw->pci.pc.destruct = genericDestruct;
1580 pcw->pci.pc.print = genericPrint;
1582 pcw->id = pCodeID; // this is the 'n' in %n
1583 pcw->operand = optional_operand;
1584 pcw->label = optional_label;
1586 pcw->mustBeBitSkipInst = 0;
1587 pcw->mustNotBeBitSkipInst = 0;
1588 pcw->invertBitSkipInst = 0;
1590 return ( (pCode *)pcw);
1594 /*-----------------------------------------------------------------*/
1595 /* newPcodeCharP - create a new pCode from a char string */
1596 /*-----------------------------------------------------------------*/
1598 pCode *newpCodeCharP(char *cP)
1603 pcc = Safe_calloc(1,sizeof(pCodeComment));
1605 pcc->pc.type = PC_COMMENT;
1606 pcc->pc.prev = pcc->pc.next = NULL;
1607 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1610 // pcc->pc.analyze = genericAnalyze;
1611 pcc->pc.destruct = genericDestruct;
1612 pcc->pc.print = genericPrint;
1615 pcc->comment = Safe_strdup(cP);
1617 pcc->comment = NULL;
1619 return ( (pCode *)pcc);
1623 /*-----------------------------------------------------------------*/
1624 /* newpCodeFunction - */
1625 /*-----------------------------------------------------------------*/
1628 pCode *newpCodeFunction(char *mod,char *f)
1632 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1633 //_ALLOC(pcf,sizeof(pCodeFunction));
1635 pcf->pc.type = PC_FUNCTION;
1636 pcf->pc.prev = pcf->pc.next = NULL;
1637 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1640 // pcf->pc.analyze = genericAnalyze;
1641 pcf->pc.destruct = genericDestruct;
1642 pcf->pc.print = pCodePrintFunction;
1645 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1646 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1647 strcpy(pcf->modname,mod);
1649 pcf->modname = NULL;
1652 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1653 pcf->fname = Safe_calloc(1,strlen(f)+1);
1654 strcpy(pcf->fname,f);
1658 return ( (pCode *)pcf);
1662 /*-----------------------------------------------------------------*/
1664 /*-----------------------------------------------------------------*/
1667 pCode *newpCodeFlow(void )
1671 //_ALLOC(pcflow,sizeof(pCodeFlow));
1672 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1674 pcflow->pc.type = PC_FLOW;
1675 pcflow->pc.prev = pcflow->pc.next = NULL;
1676 //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1677 pcflow->pc.pb = NULL;
1679 // pcflow->pc.analyze = genericAnalyze;
1680 pcflow->pc.destruct = genericDestruct;
1681 pcflow->pc.print = genericPrint;
1683 pcflow->pc.seq = GpcFlowSeq++;
1686 pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1688 pcflow->from = pcflow->to = NULL;
1690 pcflow->inCond = PCC_NONE;
1691 pcflow->outCond = PCC_NONE;
1694 return ( (pCode *)pcflow);
1698 /*-----------------------------------------------------------------*/
1699 /* pCodeLabelDestruct - free memory used by a label. */
1700 /*-----------------------------------------------------------------*/
1701 static void pCodeLabelDestruct(pCode *pc)
1707 if((pc->type == PC_LABEL) && PCL(pc)->label)
1708 free(PCL(pc)->label);
1714 pCode *newpCodeLabel(char *name, int key)
1720 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1722 pcl->pc.type = PC_LABEL;
1723 pcl->pc.prev = pcl->pc.next = NULL;
1724 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1727 // pcl->pc.analyze = genericAnalyze;
1728 pcl->pc.destruct = pCodeLabelDestruct;
1729 pcl->pc.print = pCodePrintLabel;
1735 sprintf(s,"_%05d_DS_",key);
1740 pcl->label = Safe_strdup(s);
1743 return ( (pCode *)pcl);
1748 /*-----------------------------------------------------------------*/
1749 /* newpBlock - create and return a pointer to a new pBlock */
1750 /*-----------------------------------------------------------------*/
1751 pBlock *newpBlock(void)
1756 PpB = Safe_calloc(1,sizeof(pBlock) );
1757 PpB->next = PpB->prev = NULL;
1759 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1760 PpB->tregisters = NULL;
1767 /*-----------------------------------------------------------------*/
1768 /* newpCodeChain - create a new chain of pCodes */
1769 /*-----------------------------------------------------------------*
1771 * This function will create a new pBlock and the pointer to the
1772 * pCode that is passed in will be the first pCode in the block.
1773 *-----------------------------------------------------------------*/
1776 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1779 pBlock *pB = newpBlock();
1781 pB->pcHead = pB->pcTail = pc;
1788 /*-----------------------------------------------------------------*/
1789 /* newpCodeOpLabel - Create a new label given the key */
1790 /* Note, a negative key means that the label is part of wild card */
1791 /* (and hence a wild card label) used in the pCodePeep */
1792 /* optimizations). */
1793 /*-----------------------------------------------------------------*/
1795 pCodeOp *newpCodeOpLabel(char *name, int key)
1798 static int label_key=-1;
1802 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1803 pcop->type = PO_LABEL;
1808 sprintf(s=buffer,"_%05d_DS_",key);
1810 s = name, key = label_key--;
1813 pcop->name = Safe_strdup(s);
1815 ((pCodeOpLabel *)pcop)->key = key;
1820 /*-----------------------------------------------------------------*/
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *newpCodeOpLit(int lit)
1828 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1829 pcop->type = PO_LITERAL;
1833 sprintf(s,"0x%02x",lit);
1835 pcop->name = Safe_strdup(s);
1838 ((pCodeOpLit *)pcop)->lit = lit;
1843 /*-----------------------------------------------------------------*/
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *newpCodeOpImmd(char *name, int offset)
1849 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1850 pcop->type = PO_IMMEDIATE;
1852 pcop->name = Safe_strdup(name);
1853 fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
1859 PCOI(pcop)->offset = offset;
1864 /*-----------------------------------------------------------------*/
1865 /*-----------------------------------------------------------------*/
1866 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
1872 if(!pcwb || !subtype) {
1873 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1877 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1878 pcop->type = PO_WILD;
1879 sprintf(s,"%%%d",id);
1880 pcop->name = Safe_strdup(s);
1882 PCOW(pcop)->id = id;
1883 PCOW(pcop)->pcwb = pcwb;
1884 PCOW(pcop)->subtype = subtype;
1885 PCOW(pcop)->matched = NULL;
1890 /*-----------------------------------------------------------------*/
1891 /*-----------------------------------------------------------------*/
1892 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1896 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1897 pcop->type = PO_GPR_BIT;
1899 pcop->name = Safe_strdup(s);
1903 PCORB(pcop)->bit = bit;
1904 PCORB(pcop)->inBitSpace = inBitSpace;
1909 /*-----------------------------------------------------------------*
1910 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
1912 * If rIdx >=0 then a specific register from the set of registers
1913 * will be selected. If rIdx <0, then a new register will be searched
1915 *-----------------------------------------------------------------*/
1917 pCodeOp *newpCodeOpReg(int rIdx)
1921 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1926 PCOR(pcop)->rIdx = rIdx;
1927 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1929 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
1932 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1933 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
1936 pcop->type = PCOR(pcop)->r->pc_type;
1941 pCodeOp *newpCodeOpRegFromStr(char *name)
1945 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1946 PCOR(pcop)->r = allocRegByName(name, 1);
1947 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1948 pcop->type = PCOR(pcop)->r->pc_type;
1949 pcop->name = PCOR(pcop)->r->name;
1954 /*-----------------------------------------------------------------*/
1955 /*-----------------------------------------------------------------*/
1957 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1964 pcop = newpCodeOpBit(name, -1,0);
1968 pcop = newpCodeOpLit(-1);
1972 pcop = newpCodeOpLabel(NULL,-1);
1975 pcop = newpCodeOpReg(-1);
1979 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1982 pcop->name = Safe_strdup(name);
1990 /*-----------------------------------------------------------------*/
1991 /*-----------------------------------------------------------------*/
1992 void pCodeConstString(char *name, char *value)
1996 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2001 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2005 sprintf(buffer,"; %s = %s",name,value);
2007 addpCode2pBlock(pb,newpCodeCharP(buffer));
2008 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2011 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2017 /*-----------------------------------------------------------------*/
2018 /*-----------------------------------------------------------------*/
2019 void pCodeReadCodeTable(void)
2023 fprintf(stderr, " %s\n",__FUNCTION__);
2025 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2029 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2030 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2031 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2032 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2034 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2035 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2036 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2037 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2042 /*-----------------------------------------------------------------*/
2043 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2044 /*-----------------------------------------------------------------*/
2045 void addpCode2pBlock(pBlock *pb, pCode *pc)
2048 /* If this is the first pcode to be added to a block that
2049 * was initialized with a NULL pcode, then go ahead and
2050 * make this pcode the head and tail */
2051 pb->pcHead = pb->pcTail = pc;
2053 pb->pcTail->next = pc;
2054 pc->prev = pb->pcTail;
2061 /*-----------------------------------------------------------------*/
2062 /* addpBlock - place a pBlock into the pFile */
2063 /*-----------------------------------------------------------------*/
2064 void addpBlock(pBlock *pb)
2066 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2069 /* First time called, we'll pass through here. */
2070 //_ALLOC(the_pFile,sizeof(pFile));
2071 the_pFile = Safe_calloc(1,sizeof(pFile));
2072 the_pFile->pbHead = the_pFile->pbTail = pb;
2073 the_pFile->functions = NULL;
2077 the_pFile->pbTail->next = pb;
2078 pb->prev = the_pFile->pbTail;
2080 the_pFile->pbTail = pb;
2083 /*-----------------------------------------------------------------*/
2084 /* printpCode - write the contents of a pCode to a file */
2085 /*-----------------------------------------------------------------*/
2086 void printpCode(FILE *of, pCode *pc)
2097 fprintf(of,"warning - unable to print pCode\n");
2100 /*-----------------------------------------------------------------*/
2101 /* printpBlock - write the contents of a pBlock to a file */
2102 /*-----------------------------------------------------------------*/
2103 void printpBlock(FILE *of, pBlock *pb)
2113 for(pc = pb->pcHead; pc; pc = pc->next)
2118 /*-----------------------------------------------------------------*/
2120 /* pCode processing */
2124 /*-----------------------------------------------------------------*/
2126 static void unlinkPC(pCode *pc)
2132 pc->prev->next = pc->next;
2134 pc->next->prev = pc->prev;
2136 pc->prev = pc->next = NULL;
2139 static void genericDestruct(pCode *pc)
2141 fprintf(stderr,"warning, calling default pCode destructor\n");
2150 /*-----------------------------------------------------------------*/
2151 /*-----------------------------------------------------------------*/
2152 void pBlockRegs(FILE *of, pBlock *pb)
2157 r = setFirstItem(pb->tregisters);
2159 r = setNextItem(pb->tregisters);
2164 static char *get_op( pCodeInstruction *pcc)
2167 static char buffer[50];
2171 if(pcc && pcc->pcop) {
2174 switch(pcc->pcop->type) {
2177 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2178 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2180 return PCOR(pcc->pcop)->r->name;
2183 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
2184 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2185 pBlockRegs(stderr,pcc->pc.pb);
2189 // return PCOR(pcc->pcop)->r)->name;
2192 size = sizeof(buffer);
2196 if( PCOI(pcc->pcop)->offset && PCOI(pcc->pcop)->offset<4) {
2197 SAFE_snprintf(&s,&size,"((%s >> %d)&0xff)",
2199 8 * PCOI(pcc->pcop)->offset );
2201 SAFE_snprintf(&s,&size,"LOW(%s)",pcc->pcop->name);
2204 if( PCOI(pcc->pcop)->offset && PCOI(pcc->pcop)->offset<4) {
2205 SAFE_snprintf(&s,&size,"(%s + %d)",
2207 PCOI(pcc->pcop)->offset );
2209 SAFE_snprintf(&s,&size,"%s",pcc->pcop->name);
2214 size = sizeof(buffer);
2215 if( PCOR(pcc->pcop)->instance) {
2216 SAFE_snprintf(&s,&size,"(%s + %d)",
2218 PCOR(pcc->pcop)->instance );
2219 fprintf(stderr,"PO_DIR %s\n",buffer);
2221 SAFE_snprintf(&s,&size,"%s",pcc->pcop->name);
2225 if (pcc->pcop->name)
2226 return pcc->pcop->name;
2231 return "NO operand";
2234 /*-----------------------------------------------------------------*/
2235 /*-----------------------------------------------------------------*/
2236 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2239 fprintf(of,"pcodeopprint\n");
2242 char *pCode2str(char *str, int size, pCode *pc)
2250 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2252 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2254 if(PCI(pc)->isBitInst) {
2255 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2256 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2257 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2258 PCI(pc)->pcop->name ,
2259 PCI(pc)->pcop->name );
2261 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
2262 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2263 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2264 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2266 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
2267 //PCI(pc)->pcop->t.bit );
2270 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2271 if( PCI(pc)->num_ops == 2)
2272 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2274 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
2277 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
2279 if( PCI(pc)->num_ops == 2)
2280 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2288 /* assuming that comment ends with a \n */
2289 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2293 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2296 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2299 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2302 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2310 /*-----------------------------------------------------------------*/
2311 /* genericPrint - the contents of a pCode to a file */
2312 /*-----------------------------------------------------------------*/
2313 static void genericPrint(FILE *of, pCode *pc)
2321 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2325 // If the opcode has a label, print that first
2327 pBranch *pbl = PCI(pc)->label;
2328 while(pbl && pbl->pc) {
2329 if(pbl->pc->type == PC_LABEL)
2330 pCodePrintLabel(of, pbl->pc);
2339 pCode2str(str, 256, pc);
2341 fprintf(of,"%s",str);
2344 fprintf(of, "\t;key=%03x",pc->seq);
2346 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2350 pBranch *dpb = pc->to; // debug
2352 switch ( dpb->pc->type) {
2354 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2357 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2360 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2363 fprintf(of, "\t;flow");
2377 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2378 if(PCW(pc)->pci.label)
2379 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2381 if(PCW(pc)->operand) {
2382 fprintf(of,";\toperand ");
2383 pCodeOpPrint(of,PCW(pc)->operand );
2388 fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2393 fprintf(of,"unknown pCode type %d\n",pc->type);
2398 /*-----------------------------------------------------------------*/
2399 /* pCodePrintFunction - prints function begin/end */
2400 /*-----------------------------------------------------------------*/
2402 static void pCodePrintFunction(FILE *of, pCode *pc)
2408 if( ((pCodeFunction *)pc)->modname)
2409 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2411 if(PCF(pc)->fname) {
2412 pBranch *exits = PCF(pc)->to;
2414 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2417 exits = exits->next;
2420 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2423 if((PCF(pc)->from &&
2424 PCF(pc)->from->pc->type == PC_FUNCTION &&
2425 PCF(PCF(pc)->from->pc)->fname) )
2426 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2428 fprintf(of,"; exit point [can't find entry point]\n");
2431 /*-----------------------------------------------------------------*/
2432 /* pCodePrintLabel - prints label */
2433 /*-----------------------------------------------------------------*/
2435 static void pCodePrintLabel(FILE *of, pCode *pc)
2442 fprintf(of,"%s\n",PCL(pc)->label);
2443 else if (PCL(pc)->key >=0)
2444 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2446 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2449 /*-----------------------------------------------------------------*/
2450 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2451 /* remove it if it is found. */
2452 /*-----------------------------------------------------------------*/
2453 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2460 if(pcl->type == PC_OPCODE)
2461 b = PCI(pcl)->label;
2463 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2473 bprev->next = b->next; /* Not first pCode in chain */
2477 PCI(pcl)->label = b->next; /* First pCode in chain */
2480 return; /* A label can't occur more than once */
2497 bprev->next = b->next; /* Not first pCode in chain */
2501 pcl->label = b->next; /* First pCode in chain */
2504 return; /* A label can't occur more than once */
2512 /*-----------------------------------------------------------------*/
2513 /*-----------------------------------------------------------------*/
2514 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2530 /*-----------------------------------------------------------------*/
2531 /* pBranchLink - given two pcodes, this function will link them */
2532 /* together through their pBranches */
2533 /*-----------------------------------------------------------------*/
2534 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2538 // Declare a new branch object for the 'from' pCode.
2540 //_ALLOC(b,sizeof(pBranch));
2541 b = Safe_calloc(1,sizeof(pBranch));
2542 b->pc = PCODE(t); // The link to the 'to' pCode.
2545 f->to = pBranchAppend(f->to,b);
2547 // Now do the same for the 'to' pCode.
2549 //_ALLOC(b,sizeof(pBranch));
2550 b = Safe_calloc(1,sizeof(pBranch));
2554 t->from = pBranchAppend(t->from,b);
2559 /*-----------------------------------------------------------------*/
2560 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2562 /*-----------------------------------------------------------------*/
2563 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2576 /*-----------------------------------------------------------------*/
2577 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2578 /*-----------------------------------------------------------------*/
2579 static void pCodeUnlink(pCode *pc)
2584 if(!pc->prev || !pc->next) {
2585 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2589 /* first remove the pCode from the chain */
2590 pc->prev->next = pc->next;
2591 pc->next->prev = pc->prev;
2593 /* Now for the hard part... */
2595 /* Remove the branches */
2599 pc1 = pb1->pc; /* Get the pCode that branches to the
2600 * one we're unlinking */
2602 /* search for the link back to this pCode (the one we're
2604 if(pb2 = pBranchFind(pc1->to,pc)) {
2605 pb2->pc = pc->to->pc; // make the replacement
2607 /* if the pCode we're unlinking contains multiple 'to'
2608 * branches (e.g. this a skip instruction) then we need
2609 * to copy these extra branches to the chain. */
2611 pBranchAppend(pb2, pc->to->next);
2620 /*-----------------------------------------------------------------*/
2621 /*-----------------------------------------------------------------*/
2623 static void genericAnalyze(pCode *pc)
2633 // Go through the pCodes that are in pCode chain and link
2634 // them together through the pBranches. Note, the pCodes
2635 // are linked together as a contiguous stream like the
2636 // assembly source code lines. The linking here mimics this
2637 // except that comments are not linked in.
2639 pCode *npc = pc->next;
2641 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2642 pBranchLink(pc,npc);
2647 /* reached the end of the pcode chain without finding
2648 * an instruction we could link to. */
2652 fprintf(stderr,"analyze PC_FLOW\n");
2659 /*-----------------------------------------------------------------*/
2660 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2664 if(pc->type == PC_LABEL) {
2665 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2668 if(pc->type == PC_OPCODE) {
2669 pbr = PCI(pc)->label;
2671 if(pbr->pc->type == PC_LABEL) {
2672 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2682 /*-----------------------------------------------------------------*/
2683 /* findLabel - Search the pCode for a particular label */
2684 /*-----------------------------------------------------------------*/
2685 pCode * findLabel(pCodeOpLabel *pcop_label)
2693 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2694 for(pc = pb->pcHead; pc; pc = pc->next)
2695 if(compareLabel(pc,pcop_label))
2700 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2704 /*-----------------------------------------------------------------*/
2705 /* findNextpCode - given a pCode, find the next of type 'pct' */
2706 /* in the linked list */
2707 /*-----------------------------------------------------------------*/
2708 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2721 /*-----------------------------------------------------------------*/
2722 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2723 /* in the linked list */
2724 /*-----------------------------------------------------------------*/
2725 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2737 /*-----------------------------------------------------------------*/
2738 /* findNextInstruction - given a pCode, find the next instruction */
2739 /* in the linked list */
2740 /*-----------------------------------------------------------------*/
2741 pCode * findNextInstruction(pCode *pc)
2745 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2751 //fprintf(stderr,"Couldn't find instruction\n");
2755 /*-----------------------------------------------------------------*/
2756 /* findFunctionEnd - given a pCode find the end of the function */
2757 /* that contains it t */
2758 /*-----------------------------------------------------------------*/
2759 pCode * findFunctionEnd(pCode *pc)
2763 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2769 fprintf(stderr,"Couldn't find function end\n");
2774 /*-----------------------------------------------------------------*/
2775 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2776 /* instruction with which it is associated. */
2777 /*-----------------------------------------------------------------*/
2778 static void AnalyzeLabel(pCode *pc)
2787 static void AnalyzeGOTO(pCode *pc)
2790 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2794 static void AnalyzeSKIP(pCode *pc)
2797 pBranchLink(pc,findNextInstruction(pc->next));
2798 pBranchLink(pc,findNextInstruction(pc->next->next));
2802 static void AnalyzeRETURN(pCode *pc)
2805 // branch_link(pc,findFunctionEnd(pc->next));
2811 /*-----------------------------------------------------------------*/
2812 /*-----------------------------------------------------------------*/
2813 regs * getRegFromInstruction(pCode *pc)
2818 PCI(pc)->num_ops == 0 )
2821 switch(PCI(pc)->pcop->type) {
2824 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2828 fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2829 return PCOR(PCI(pc)->pcop)->r;
2832 fprintf(stderr, "getRegFromInstruction - immediate\n");
2833 return NULL; // PCOR(PCI(pc)->pcop)->r;
2836 return PCOR(PCI(pc)->pcop)->r;
2839 fprintf(stderr, "getRegFromInstruction - dir\n");
2840 //return NULL; PCOR(PCI(pc)->pcop)->r;
2841 return PCOR(PCI(pc)->pcop)->r;
2843 fprintf(stderr, "getRegFromInstruction - literal\n");
2847 fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2848 genericPrint(stderr, pc);
2856 /*-----------------------------------------------------------------*/
2857 /*-----------------------------------------------------------------*/
2859 void AnalyzepBlock(pBlock *pb)
2866 /* Find all of the registers used in this pBlock
2867 * by looking at each instruction and examining it's
2870 for(pc = pb->pcHead; pc; pc = pc->next) {
2872 /* Is this an instruction with operands? */
2873 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2875 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2877 /* Loop through all of the registers declared so far in
2878 this block and see if we find this one there */
2880 regs *r = setFirstItem(pb->tregisters);
2883 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2884 PCOR(PCI(pc)->pcop)->r = r;
2887 r = setNextItem(pb->tregisters);
2891 /* register wasn't found */
2892 r = Safe_calloc(1, sizeof(regs));
2893 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2894 addSet(&pb->tregisters, r);
2895 PCOR(PCI(pc)->pcop)->r = r;
2896 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2898 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2901 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2902 if(PCOR(PCI(pc)->pcop)->r) {
2903 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2904 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2906 if(PCI(pc)->pcop->name)
2907 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2909 fprintf(stderr,"ERROR: NULL register\n");
2918 /*-----------------------------------------------------------------*/
2920 /*-----------------------------------------------------------------*/
2921 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2923 void InsertpFlow(pCode *pc, pCode **pflow)
2925 PCFL(*pflow)->end = pc;
2927 if(!pc || !pc->next)
2930 *pflow = newpCodeFlow();
2931 pCodeInsertAfter(pc, *pflow);
2934 /*-----------------------------------------------------------------*/
2935 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
2936 /* the flow blocks. */
2938 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2939 * point the instruction flow changes.
2941 /*-----------------------------------------------------------------*/
2942 void BuildFlow(pBlock *pb)
2945 pCode *last_pci=NULL;
2952 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
2953 /* Insert a pCodeFlow object at the beginning of a pBlock */
2955 pflow = newpCodeFlow(); /* Create a new Flow object */
2956 pflow->next = pb->pcHead; /* Make the current head the next object */
2957 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
2958 pb->pcHead = pflow; /* Make the Flow object the head */
2961 for( pc = findNextInstruction(pb->pcHead);
2962 (pc=findNextInstruction(pc)) != NULL; ) {
2965 PCI(pc)->pcflow = PCFL(pflow);
2967 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
2969 /* The instruction immediately following this one
2970 * marks the beginning of a new flow segment */
2972 InsertpFlow(pc, &pflow);
2975 } else if (PCI_HAS_LABEL(pc)) {
2977 /* This instruction marks the beginning of a
2978 * new flow segment */
2982 InsertpFlow(pc->prev, &pflow);
2984 PCI(pc)->pcflow = PCFL(pflow);
2991 //fprintf (stderr,",end seq %d",GpcFlowSeq);
2992 PCFL(pflow)->end = pb->pcTail;
2995 /*-----------------------------------------------------------------*/
2996 /*-----------------------------------------------------------------*/
2997 void dumpCond(int cond)
3000 static char *pcc_str[] = {
3014 int ncond = sizeof(pcc_str) / sizeof(char *);
3017 fprintf(stderr, "0x%04X\n",cond);
3019 for(i=0,j=1; i<ncond; i++, j<<=1)
3021 fprintf(stderr, " %s\n",pcc_str[i]);
3025 /*-----------------------------------------------------------------*/
3026 /*-----------------------------------------------------------------*/
3027 void FillFlow(pCodeFlow *pcflow)
3036 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3038 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3040 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3049 int inCond = PCI(pc)->inCond;
3050 int outCond = PCI(pc)->outCond;
3052 if( (reg = getRegFromInstruction(pc)) != NULL) {
3053 if(isSTATUS_REG(reg)) {
3055 //fprintf(stderr, " FillFlow - Status register\n");
3057 /* Check to see if the register banks are changing */
3058 if(PCI(pc)->isModReg) {
3060 pCodeOp *pcop = PCI(pc)->pcop;
3061 switch(PCI(pc)->op) {
3063 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3064 fprintf(stderr, " FillFlow - Set RP0\n");
3065 //outCond |= PCC_REG_BANK1;
3066 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3067 fprintf(stderr, " FillFlow - Set RP1\n");
3068 //outCond |= PCC_REG_BANK3;
3072 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3073 fprintf(stderr, " FillFlow - Clr RP0\n");
3074 //outCond |= PCC_REG_BANK1;
3075 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3076 fprintf(stderr, " FillFlow - Clr RP1\n");
3077 //outCond |= PCC_REG_BANK3;
3081 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3082 genericPrint(stderr, pc);
3087 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3091 pcflow->inCond |= (inCond & ~pcflow->outCond);
3092 pcflow->outCond |= outCond;
3097 pc = findNextpCode(pc->next, PC_OPCODE);
3098 } while (pc && (pc != pcflow->end));
3102 fprintf(stderr, " FillFlow - Bad end of flow\n");
3105 fprintf(stderr, " FillFlow inCond: ");
3106 dumpCond(pcflow->inCond);
3107 fprintf(stderr, " FillFlow outCond: ");
3108 dumpCond(pcflow->outCond);
3111 /*-----------------------------------------------------------------*/
3112 /*-----------------------------------------------------------------*/
3113 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3116 if(!from || !to || !to->pcflow || !from->pcflow)
3119 addSet(&(from->pcflow->to), to->pcflow);
3120 addSet(&(to->pcflow->from), from->pcflow);
3124 /*-----------------------------------------------------------------*/
3125 /*-----------------------------------------------------------------*/
3126 void LinkFlow(pBlock *pb)
3133 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3134 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3135 pcflow = pcflow->next) {
3138 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3140 //FillFlow(PCFL(pcflow));
3142 pc = PCFL(pcflow)->end;
3144 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3145 if(isPCI_SKIP(pc)) {
3146 //fprintf(stderr, "ends with skip\n");
3147 pct=findNextInstruction(pc->next);
3148 LinkFlow_pCode(PCI(pc),PCI(pct));
3149 pct=findNextInstruction(pct->next);
3150 LinkFlow_pCode(PCI(pc),PCI(pct));
3154 if(isPCI_BRANCH(pc)) {
3155 //fprintf(stderr, "ends with branch\n");
3161 fprintf(stderr, "has an unrecognized ending:\n");
3162 pc->print(stderr,pc);
3165 fprintf(stderr, "has no end pcode\n");
3170 /*-----------------------------------------------------------------*/
3171 /*-----------------------------------------------------------------*/
3172 int OptimizepBlock(pBlock *pb)
3177 if(!pb || !peepOptimizing)
3180 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3181 for(pc = pb->pcHead; pc; pc = pc->next)
3182 matches += pCodePeepMatchRule(pc);
3184 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3189 /*-----------------------------------------------------------------*/
3190 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3191 /*-----------------------------------------------------------------*/
3192 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3196 for(pc = pcs; pc; pc = pc->next) {
3198 if((pc->type == PC_OPCODE) &&
3200 (PCI(pc)->pcop->type == PO_LABEL) &&
3201 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3209 /*-----------------------------------------------------------------*/
3210 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3211 /* pCode chain if they're not used. */
3212 /*-----------------------------------------------------------------*/
3213 void pBlockRemoveUnusedLabels(pBlock *pb)
3215 pCode *pc; pCodeLabel *pcl;
3220 for(pc = pb->pcHead; pc; pc = pc->next) {
3222 if(pc->type == PC_LABEL)
3224 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3225 pcl = PCL(PCI(pc)->label->pc);
3228 /* This pCode is a label, so search the pBlock to see if anyone
3231 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3232 /* Couldn't find an instruction that refers to this label
3233 * So, unlink the pCode label from it's pCode chain
3234 * and destroy the label */
3236 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3238 if(pc->type == PC_LABEL) {
3240 pCodeLabelDestruct(pc);
3242 unlinkpCodeFromBranch(pc, PCODE(pcl));
3243 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3254 /*-----------------------------------------------------------------*/
3255 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3256 /* chain and put them into pBranches that are */
3257 /* associated with the appropriate pCode */
3259 /*-----------------------------------------------------------------*/
3260 void pBlockMergeLabels(pBlock *pb)
3263 pCode *pc, *pcnext=NULL;
3268 /* First, Try to remove any unused labels */
3269 //pBlockRemoveUnusedLabels(pb);
3271 /* Now loop through the pBlock and merge the labels with the opcodes */
3273 for(pc = pb->pcHead; pc; pc = pc->next) {
3275 if(pc->type == PC_LABEL) {
3276 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3277 if( !(pcnext = findNextInstruction(pc)) )
3278 return; // Couldn't find an instruction associated with this label
3280 // Unlink the pCode label from it's pCode chain
3283 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3284 // And link it into the instruction's pBranch labels. (Note, since
3285 // it's possible to have multiple labels associated with one instruction
3286 // we must provide a means to accomodate the additional labels. Thus
3287 // the labels are placed into the singly-linked list "label" as
3288 // opposed to being a single member of the pCodeInstruction.)
3290 //_ALLOC(pbr,sizeof(pBranch));
3291 pbr = Safe_calloc(1,sizeof(pBranch));
3295 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3303 pBlockRemoveUnusedLabels(pb);
3307 /*-----------------------------------------------------------------*/
3308 /*-----------------------------------------------------------------*/
3309 void OptimizepCode(char dbName)
3311 #define MAX_PASSES 4
3320 DFPRINTF((stderr," Optimizing pCode\n"));
3323 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3324 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3325 matches += OptimizepBlock(pb);
3328 while(matches && ++passes < MAX_PASSES);
3332 /*-----------------------------------------------------------------*/
3333 /* popCopyGPR2Bit - copy a pcode operator */
3334 /*-----------------------------------------------------------------*/
3336 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3340 pcop = newpCodeOpBit(pc->name, bitval, 0);
3342 if( !( (pcop->type == PO_LABEL) ||
3343 (pcop->type == PO_LITERAL) ||
3344 (pcop->type == PO_STR) ))
3345 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3353 /*-----------------------------------------------------------------*/
3354 /*-----------------------------------------------------------------*/
3355 int InstructionRegBank(pCode *pc)
3359 if( (reg = getRegFromInstruction(pc)) == NULL)
3362 return REG_BANK(reg);
3367 /*-----------------------------------------------------------------*/
3368 /*-----------------------------------------------------------------*/
3369 void FixRegisterBanking(pBlock *pb)
3381 pc = findNextpCode(pb->pcHead, PC_FLOW);
3384 /* loop through all of the flow blocks with in one pblock */
3386 // fprintf(stderr,"Register banking\n");
3389 /* at this point, pc should point to a PC_FLOW object */
3392 /* for each flow block, determine the register banking
3397 genericPrint(stderr, pc);
3399 reg = getRegFromInstruction(pc);
3402 fprintf(stderr, " %s ",reg->name);
3403 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3407 if(reg && REG_BANK(reg)!=cur_bank) {
3408 /* Examine the instruction before this one to make sure it is
3409 * not a skip type instruction */
3410 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3411 if(pcprev && !isPCI_SKIP(pcprev)) {
3412 int b = cur_bank ^ REG_BANK(reg);
3414 //fprintf(stderr, "Cool! can switch banks\n");
3415 cur_bank = REG_BANK(reg);
3417 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3418 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3419 pCodeInsertAfter(pc->prev, new_pc);
3420 if(PCI(pc)->label) {
3421 PCI(new_pc)->label = PCI(pc)->label;
3422 PCI(pc)->label = NULL;
3425 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3426 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3427 pCodeInsertAfter(pc, new_pc);
3433 fprintf(stderr, "Bummer can't switch banks\n");
3439 } while(pc && !(isPCFL(pc)));
3441 if(pcprev && cur_bank) {
3442 /* Brute force - make sure that we point to bank 0 at the
3443 * end of each flow block */
3444 new_pc = newpCode(POC_BCF,
3445 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3446 pCodeInsertAfter(pcprev, new_pc);
3454 void pBlockDestruct(pBlock *pb)
3465 /*-----------------------------------------------------------------*/
3466 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3467 /* name dbName and combine them */
3468 /* into one block */
3469 /*-----------------------------------------------------------------*/
3470 void mergepBlocks(char dbName)
3473 pBlock *pb, *pbmerged = NULL,*pbn;
3475 pb = the_pFile->pbHead;
3477 //fprintf(stderr," merging blocks named %c\n",dbName);
3481 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3482 if( getpBlock_dbName(pb) == dbName) {
3484 //fprintf(stderr," merged block %c\n",dbName);
3489 addpCode2pBlock(pbmerged, pb->pcHead);
3490 /* addpCode2pBlock doesn't handle the tail: */
3491 pbmerged->pcTail = pb->pcTail;
3493 pb->prev->next = pbn;
3495 pbn->prev = pb->prev;
3500 //printpBlock(stderr, pbmerged);
3507 /*-----------------------------------------------------------------*/
3508 /* AnalyzeBanking - Called after the memory addresses have been */
3509 /* assigned to the registers. */
3511 /*-----------------------------------------------------------------*/
3512 void AnalyzeBanking(void)
3521 /* Phase 2 - Flow Analysis
3523 * In this phase, the pCode is partition into pCodeFlow
3524 * blocks. The flow blocks mark the points where a continuous
3525 * stream of instructions changes flow (e.g. because of
3526 * a call or goto or whatever).
3529 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3532 /* Phase 2 - Flow Analysis - linking flow blocks
3534 * In this phase, the individual flow blocks are examined
3535 * to determine their order of excution.
3538 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3541 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3542 FixRegisterBanking(pb);
3545 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3547 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3548 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3549 pcflow = pcflow->next) {
3551 FillFlow(PCFL(pcflow));
3558 /*-----------------------------------------------------------------*/
3559 /* buildCallTree - look at the flow and extract all of the calls */
3561 /*-----------------------------------------------------------------*/
3562 set *register_usage(pBlock *pb);
3564 void buildCallTree(void )
3575 /* Now build the call tree.
3576 First we examine all of the pCodes for functions.
3577 Keep in mind that the function boundaries coincide
3578 with pBlock boundaries.
3580 The algorithm goes something like this:
3581 We have two nested loops. The outer loop iterates
3582 through all of the pBlocks/functions. The inner
3583 loop iterates through all of the pCodes for
3584 a given pBlock. When we begin iterating through
3585 a pBlock, the variable pc_fstart, pCode of the start
3586 of a function, is cleared. We then search for pCodes
3587 of type PC_FUNCTION. When one is encountered, we
3588 initialize pc_fstart to this and at the same time
3589 associate a new pBranch object that signifies a
3590 branch entry. If a return is found, then this signifies
3591 a function exit point. We'll link the pCodes of these
3592 returns to the matching pc_fstart.
3594 When we're done, a doubly linked list of pBranches
3595 will exist. The head of this list is stored in
3596 `the_pFile', which is the meta structure for all
3597 of the pCode. Look at the printCallTree function
3598 on how the pBranches are linked together.
3601 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3602 pCode *pc_fstart=NULL;
3603 for(pc = pb->pcHead; pc; pc = pc->next) {
3604 if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
3605 if (PCF(pc)->fname) {
3607 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3608 //fprintf(stderr," found main \n");
3609 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3613 //_ALLOC(pbr,sizeof(pBranch));
3614 pbr = Safe_calloc(1,sizeof(pBranch));
3615 pbr->pc = pc_fstart = pc;
3618 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3620 // Here's a better way of doing the same:
3621 addSet(&pb->function_entries, pc);
3624 // Found an exit point in a function, e.g. return
3625 // (Note, there may be more than one return per function)
3627 pBranchLink(PCF(pc_fstart), PCF(pc));
3629 addSet(&pb->function_exits, pc);
3631 } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3632 addSet(&pb->function_calls,pc);
3637 /* Re-allocate the registers so that there are no collisions
3638 * between local variables when one function call another */
3640 pic14_deallocateAllRegs();
3642 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3649 /*-----------------------------------------------------------------*/
3650 /* AnalyzepCode - parse the pCode that has been generated and form */
3651 /* all of the logical connections. */
3653 /* Essentially what's done here is that the pCode flow is */
3655 /*-----------------------------------------------------------------*/
3657 void AnalyzepCode(char dbName)
3668 /* Phase 1 - Register allocation and peep hole optimization
3670 * The first part of the analysis is to determine the registers
3671 * that are used in the pCode. Once that is done, the peep rules
3672 * are applied to the code. We continue to loop until no more
3673 * peep rule optimizations are found (or until we exceed the
3674 * MAX_PASSES threshold).
3676 * When done, the required registers will be determined.
3682 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3684 /* First, merge the labels with the instructions */
3685 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3686 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3688 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3689 //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3690 pBlockMergeLabels(pb);
3697 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3698 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3699 changes += OptimizepBlock(pb);
3702 } while(changes && (i++ < MAX_PASSES));
3707 /*-----------------------------------------------------------------*/
3708 /* ispCodeFunction - returns true if *pc is the pCode of a */
3710 /*-----------------------------------------------------------------*/
3711 bool ispCodeFunction(pCode *pc)
3714 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3720 /*-----------------------------------------------------------------*/
3721 /* findFunction - Search for a function by name (given the name) */
3722 /* in the set of all functions that are in a pBlock */
3723 /* (note - I expect this to change because I'm planning to limit */
3724 /* pBlock's to just one function declaration */
3725 /*-----------------------------------------------------------------*/
3726 pCode *findFunction(char *fname)
3733 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3735 pc = setFirstItem(pb->function_entries);
3738 if((pc->type == PC_FUNCTION) &&
3740 (strcmp(fname, PCF(pc)->fname)==0))
3743 pc = setNextItem(pb->function_entries);
3751 void MarkUsedRegisters(set *regset)
3756 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3757 r2 = pic14_regWithIdx(r1->rIdx);
3763 void pBlockStats(FILE *of, pBlock *pb)
3769 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3771 // for now just print the first element of each set
3772 pc = setFirstItem(pb->function_entries);
3774 fprintf(of,";entry: ");
3777 pc = setFirstItem(pb->function_exits);
3779 fprintf(of,";has an exit\n");
3783 pc = setFirstItem(pb->function_calls);
3785 fprintf(of,";functions called:\n");
3788 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3789 fprintf(of,"; %s\n",get_op(PCI(pc)));
3791 pc = setNextItem(pb->function_calls);
3795 r = setFirstItem(pb->tregisters);
3797 int n = elementsInSet(pb->tregisters);
3799 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3802 fprintf(of,"; %s\n",r->name);
3803 r = setNextItem(pb->tregisters);
3808 /*-----------------------------------------------------------------*/
3809 /*-----------------------------------------------------------------*/
3810 static void sequencepCode(void)
3816 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3818 pb->seq = GpCodeSequenceNumber+1;
3820 for( pc = pb->pcHead; pc; pc = pc->next)
3821 pc->seq = ++GpCodeSequenceNumber;
3826 /*-----------------------------------------------------------------*/
3827 /*-----------------------------------------------------------------*/
3828 set *register_usage(pBlock *pb)
3831 set *registers=NULL;
3832 set *registersInCallPath = NULL;
3834 /* check recursion */
3836 pc = setFirstItem(pb->function_entries);
3843 if(pc->type != PC_FUNCTION)
3844 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3846 pc = setFirstItem(pb->function_calls);
3847 for( ; pc; pc = setNextItem(pb->function_calls)) {
3849 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3850 char *dest = get_op(PCI(pc));
3852 pcn = findFunction(dest);
3854 registersInCallPath = register_usage(pcn->pb);
3856 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3861 pBlockStats(stderr,pb); // debug
3864 // Mark the registers in this block as used.
3866 MarkUsedRegisters(pb->tregisters);
3867 if(registersInCallPath) {
3868 /* registers were used in the functions this pBlock has called */
3869 /* so now, we need to see if these collide with the ones we are */
3872 regs *r1,*r2, *newreg;
3874 DFPRINTF((stderr,"comparing registers\n"));
3876 r1 = setFirstItem(registersInCallPath);
3879 r2 = setFirstItem(pb->tregisters);
3881 while(r2 && (r1->type != REG_STK)) {
3883 if(r2->rIdx == r1->rIdx) {
3884 newreg = pic14_findFreeReg(REG_GPR);
3888 DFPRINTF((stderr,"Bummer, no more registers.\n"));
3892 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3893 r1->rIdx, newreg->rIdx));
3894 r2->rIdx = newreg->rIdx;
3895 //if(r2->name) free(r2->name);
3897 r2->name = Safe_strdup(newreg->name);
3901 newreg->wasUsed = 1;
3903 r2 = setNextItem(pb->tregisters);
3906 r1 = setNextItem(registersInCallPath);
3909 /* Collisions have been resolved. Now free the registers in the call path */
3910 r1 = setFirstItem(registersInCallPath);
3912 if(r1->type != REG_STK) {
3913 newreg = pic14_regWithIdx(r1->rIdx);
3916 r1 = setNextItem(registersInCallPath);
3920 // MarkUsedRegisters(pb->registers);
3922 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3925 DFPRINTF((stderr,"returning regs\n"));
3927 DFPRINTF((stderr,"not returning regs\n"));
3929 DFPRINTF((stderr,"pBlock after register optim.\n"));
3930 pBlockStats(stderr,pb); // debug
3936 /*-----------------------------------------------------------------*/
3937 /* printCallTree - writes the call tree to a file */
3939 /*-----------------------------------------------------------------*/
3940 void pct2(FILE *of,pBlock *pb,int indent)
3944 // set *registersInCallPath = NULL;
3947 return;// registers;
3950 return; // registers; //recursion ?
3952 pc = setFirstItem(pb->function_entries);
3959 for(i=0;i<indent;i++) // Indentation
3962 if(pc->type == PC_FUNCTION)
3963 fprintf(of,"%s\n",PCF(pc)->fname);
3968 pc = setFirstItem(pb->function_calls);
3969 for( ; pc; pc = setNextItem(pb->function_calls)) {
3971 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3972 char *dest = get_op(PCI(pc));
3974 pcn = findFunction(dest);
3976 pct2(of,pcn->pb,indent+1);
3978 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3986 fprintf(stderr,"pBlock before register optim.\n");
3987 pBlockStats(stderr,pb); // debug
3989 if(registersInCallPath) {
3990 /* registers were used in the functions this pBlock has called */
3991 /* so now, we need to see if these collide with the ones we are using here */
3993 regs *r1,*r2, *newreg;
3995 fprintf(stderr,"comparing registers\n");
3997 r1 = setFirstItem(registersInCallPath);
4000 r2 = setFirstItem(pb->registers);
4004 if(r2->rIdx == r1->rIdx) {
4005 newreg = pic14_findFreeReg();
4009 fprintf(stderr,"Bummer, no more registers.\n");
4013 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
4014 r1->rIdx, newreg->rIdx);
4015 r2->rIdx = newreg->rIdx;
4016 //if(r2->name) free(r2->name);
4018 r2->name = Safe_strdup(newreg->name);
4022 newreg->wasUsed = 1;
4024 r2 = setNextItem(pb->registers);
4027 r1 = setNextItem(registersInCallPath);
4030 /* Collisions have been resolved. Now free the registers in the call path */
4031 r1 = setFirstItem(registersInCallPath);
4033 newreg = pic14_regWithIdx(r1->rIdx);
4035 r1 = setNextItem(registersInCallPath);
4039 MarkUsedRegisters(pb->registers);
4041 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
4044 fprintf(stderr,"returning regs\n");
4046 fprintf(stderr,"not returning regs\n");
4048 fprintf(stderr,"pBlock after register optim.\n");
4049 pBlockStats(stderr,pb); // debug
4057 /*-----------------------------------------------------------------*/
4058 /* printCallTree - writes the call tree to a file */
4060 /*-----------------------------------------------------------------*/
4062 void printCallTree(FILE *of)
4074 fprintf(of, "\npBlock statistics\n");
4075 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4080 fprintf(of,"Call Tree\n");
4081 pbr = the_pFile->functions;
4085 if(!ispCodeFunction(pc))
4086 fprintf(of,"bug in call tree");
4089 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4091 while(pc->next && !ispCodeFunction(pc->next)) {
4093 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4094 fprintf(of,"\t%s\n",get_op(PCI(pc)));
4102 /* Re-allocate the registers so that there are no collisions
4103 * between local variables when one function call another */
4105 pic14_deallocateAllRegs();
4107 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4113 fprintf(of,"\n**************\n\na better call tree\n");
4114 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4119 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4120 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));