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, int index, int code_space)
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)->index = index;
1860 PCOI(pcop)->offset = offset;
1861 PCOI(pcop)->_const = code_space;
1866 /*-----------------------------------------------------------------*/
1867 /*-----------------------------------------------------------------*/
1868 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
1874 if(!pcwb || !subtype) {
1875 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1879 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1880 pcop->type = PO_WILD;
1881 sprintf(s,"%%%d",id);
1882 pcop->name = Safe_strdup(s);
1884 PCOW(pcop)->id = id;
1885 PCOW(pcop)->pcwb = pcwb;
1886 PCOW(pcop)->subtype = subtype;
1887 PCOW(pcop)->matched = NULL;
1892 /*-----------------------------------------------------------------*/
1893 /*-----------------------------------------------------------------*/
1894 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1898 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1899 pcop->type = PO_GPR_BIT;
1901 pcop->name = Safe_strdup(s);
1905 PCORB(pcop)->bit = bit;
1906 PCORB(pcop)->inBitSpace = inBitSpace;
1911 /*-----------------------------------------------------------------*
1912 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
1914 * If rIdx >=0 then a specific register from the set of registers
1915 * will be selected. If rIdx <0, then a new register will be searched
1917 *-----------------------------------------------------------------*/
1919 pCodeOp *newpCodeOpReg(int rIdx)
1923 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1928 PCOR(pcop)->rIdx = rIdx;
1929 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1931 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
1934 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1935 //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
1938 pcop->type = PCOR(pcop)->r->pc_type;
1943 pCodeOp *newpCodeOpRegFromStr(char *name)
1947 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1948 PCOR(pcop)->r = allocRegByName(name, 1);
1949 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1950 pcop->type = PCOR(pcop)->r->pc_type;
1951 pcop->name = PCOR(pcop)->r->name;
1956 /*-----------------------------------------------------------------*/
1957 /*-----------------------------------------------------------------*/
1959 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1966 pcop = newpCodeOpBit(name, -1,0);
1970 pcop = newpCodeOpLit(-1);
1974 pcop = newpCodeOpLabel(NULL,-1);
1977 pcop = newpCodeOpReg(-1);
1981 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1984 pcop->name = Safe_strdup(name);
1992 /*-----------------------------------------------------------------*/
1993 /*-----------------------------------------------------------------*/
1994 void pCodeConstString(char *name, char *value)
1998 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2003 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2007 sprintf(buffer,"; %s = %s",name,value);
2009 addpCode2pBlock(pb,newpCodeCharP(buffer));
2010 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2013 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2019 /*-----------------------------------------------------------------*/
2020 /*-----------------------------------------------------------------*/
2021 void pCodeReadCodeTable(void)
2025 fprintf(stderr, " %s\n",__FUNCTION__);
2027 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2031 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2032 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2033 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2034 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2036 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2037 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2038 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2039 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2044 /*-----------------------------------------------------------------*/
2045 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2046 /*-----------------------------------------------------------------*/
2047 void addpCode2pBlock(pBlock *pb, pCode *pc)
2050 /* If this is the first pcode to be added to a block that
2051 * was initialized with a NULL pcode, then go ahead and
2052 * make this pcode the head and tail */
2053 pb->pcHead = pb->pcTail = pc;
2055 pb->pcTail->next = pc;
2056 pc->prev = pb->pcTail;
2063 /*-----------------------------------------------------------------*/
2064 /* addpBlock - place a pBlock into the pFile */
2065 /*-----------------------------------------------------------------*/
2066 void addpBlock(pBlock *pb)
2068 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2071 /* First time called, we'll pass through here. */
2072 //_ALLOC(the_pFile,sizeof(pFile));
2073 the_pFile = Safe_calloc(1,sizeof(pFile));
2074 the_pFile->pbHead = the_pFile->pbTail = pb;
2075 the_pFile->functions = NULL;
2079 the_pFile->pbTail->next = pb;
2080 pb->prev = the_pFile->pbTail;
2082 the_pFile->pbTail = pb;
2085 /*-----------------------------------------------------------------*/
2086 /* printpCode - write the contents of a pCode to a file */
2087 /*-----------------------------------------------------------------*/
2088 void printpCode(FILE *of, pCode *pc)
2099 fprintf(of,"warning - unable to print pCode\n");
2102 /*-----------------------------------------------------------------*/
2103 /* printpBlock - write the contents of a pBlock to a file */
2104 /*-----------------------------------------------------------------*/
2105 void printpBlock(FILE *of, pBlock *pb)
2115 for(pc = pb->pcHead; pc; pc = pc->next)
2120 /*-----------------------------------------------------------------*/
2122 /* pCode processing */
2126 /*-----------------------------------------------------------------*/
2128 static void unlinkPC(pCode *pc)
2134 pc->prev->next = pc->next;
2136 pc->next->prev = pc->prev;
2138 pc->prev = pc->next = NULL;
2141 static void genericDestruct(pCode *pc)
2143 fprintf(stderr,"warning, calling default pCode destructor\n");
2152 /*-----------------------------------------------------------------*/
2153 /*-----------------------------------------------------------------*/
2154 void pBlockRegs(FILE *of, pBlock *pb)
2159 r = setFirstItem(pb->tregisters);
2161 r = setNextItem(pb->tregisters);
2166 static char *get_op( pCodeInstruction *pcc)
2169 static char buffer[50];
2173 if(pcc && pcc->pcop) {
2176 switch(pcc->pcop->type) {
2179 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2180 //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2182 return PCOR(pcc->pcop)->r->name;
2185 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
2186 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2187 pBlockRegs(stderr,pcc->pc.pb);
2191 // return PCOR(pcc->pcop)->r)->name;
2194 size = sizeof(buffer);
2195 fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,
2196 PCOI(pcc->pcop)->offset);
2197 if(PCOI(pcc->pcop)->_const) {
2199 if( PCOI(pcc->pcop)->offset && PCOI(pcc->pcop)->offset<4) {
2200 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2202 PCOI(pcc->pcop)->index,
2203 8 * PCOI(pcc->pcop)->offset );
2205 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcc->pcop->name,PCOI(pcc->pcop)->index);
2208 if( PCOI(pcc->pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2209 SAFE_snprintf(&s,&size,"(%s + %d)",
2211 PCOI(pcc->pcop)->index );
2213 SAFE_snprintf(&s,&size,"%s",pcc->pcop->name);
2220 size = sizeof(buffer);
2221 if( PCOR(pcc->pcop)->instance) {
2222 SAFE_snprintf(&s,&size,"(%s + %d)",
2224 PCOR(pcc->pcop)->instance );
2225 fprintf(stderr,"PO_DIR %s\n",buffer);
2227 SAFE_snprintf(&s,&size,"%s",pcc->pcop->name);
2231 if (pcc->pcop->name)
2232 return pcc->pcop->name;
2237 return "NO operand";
2240 /*-----------------------------------------------------------------*/
2241 /*-----------------------------------------------------------------*/
2242 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2245 fprintf(of,"pcodeopprint\n");
2248 char *pCode2str(char *str, int size, pCode *pc)
2256 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2258 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2260 if(PCI(pc)->isBitInst) {
2261 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2262 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2263 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
2264 PCI(pc)->pcop->name ,
2265 PCI(pc)->pcop->name );
2267 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
2268 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2269 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2270 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2272 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
2273 //PCI(pc)->pcop->t.bit );
2276 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2277 if( PCI(pc)->num_ops == 2)
2278 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2280 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
2283 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
2285 if( PCI(pc)->num_ops == 2)
2286 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2294 /* assuming that comment ends with a \n */
2295 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2299 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2302 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2305 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2308 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2316 /*-----------------------------------------------------------------*/
2317 /* genericPrint - the contents of a pCode to a file */
2318 /*-----------------------------------------------------------------*/
2319 static void genericPrint(FILE *of, pCode *pc)
2327 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2331 // If the opcode has a label, print that first
2333 pBranch *pbl = PCI(pc)->label;
2334 while(pbl && pbl->pc) {
2335 if(pbl->pc->type == PC_LABEL)
2336 pCodePrintLabel(of, pbl->pc);
2345 pCode2str(str, 256, pc);
2347 fprintf(of,"%s",str);
2350 fprintf(of, "\t;key=%03x",pc->seq);
2352 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2356 pBranch *dpb = pc->to; // debug
2358 switch ( dpb->pc->type) {
2360 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2363 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2366 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2369 fprintf(of, "\t;flow");
2383 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2384 if(PCW(pc)->pci.label)
2385 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2387 if(PCW(pc)->operand) {
2388 fprintf(of,";\toperand ");
2389 pCodeOpPrint(of,PCW(pc)->operand );
2394 fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2399 fprintf(of,"unknown pCode type %d\n",pc->type);
2404 /*-----------------------------------------------------------------*/
2405 /* pCodePrintFunction - prints function begin/end */
2406 /*-----------------------------------------------------------------*/
2408 static void pCodePrintFunction(FILE *of, pCode *pc)
2414 if( ((pCodeFunction *)pc)->modname)
2415 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2417 if(PCF(pc)->fname) {
2418 pBranch *exits = PCF(pc)->to;
2420 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2423 exits = exits->next;
2426 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2429 if((PCF(pc)->from &&
2430 PCF(pc)->from->pc->type == PC_FUNCTION &&
2431 PCF(PCF(pc)->from->pc)->fname) )
2432 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2434 fprintf(of,"; exit point [can't find entry point]\n");
2437 /*-----------------------------------------------------------------*/
2438 /* pCodePrintLabel - prints label */
2439 /*-----------------------------------------------------------------*/
2441 static void pCodePrintLabel(FILE *of, pCode *pc)
2448 fprintf(of,"%s\n",PCL(pc)->label);
2449 else if (PCL(pc)->key >=0)
2450 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2452 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2455 /*-----------------------------------------------------------------*/
2456 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
2457 /* remove it if it is found. */
2458 /*-----------------------------------------------------------------*/
2459 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2466 if(pcl->type == PC_OPCODE)
2467 b = PCI(pcl)->label;
2469 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2479 bprev->next = b->next; /* Not first pCode in chain */
2483 PCI(pcl)->label = b->next; /* First pCode in chain */
2486 return; /* A label can't occur more than once */
2503 bprev->next = b->next; /* Not first pCode in chain */
2507 pcl->label = b->next; /* First pCode in chain */
2510 return; /* A label can't occur more than once */
2518 /*-----------------------------------------------------------------*/
2519 /*-----------------------------------------------------------------*/
2520 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2536 /*-----------------------------------------------------------------*/
2537 /* pBranchLink - given two pcodes, this function will link them */
2538 /* together through their pBranches */
2539 /*-----------------------------------------------------------------*/
2540 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2544 // Declare a new branch object for the 'from' pCode.
2546 //_ALLOC(b,sizeof(pBranch));
2547 b = Safe_calloc(1,sizeof(pBranch));
2548 b->pc = PCODE(t); // The link to the 'to' pCode.
2551 f->to = pBranchAppend(f->to,b);
2553 // Now do the same for the 'to' pCode.
2555 //_ALLOC(b,sizeof(pBranch));
2556 b = Safe_calloc(1,sizeof(pBranch));
2560 t->from = pBranchAppend(t->from,b);
2565 /*-----------------------------------------------------------------*/
2566 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2568 /*-----------------------------------------------------------------*/
2569 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2582 /*-----------------------------------------------------------------*/
2583 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
2584 /*-----------------------------------------------------------------*/
2585 static void pCodeUnlink(pCode *pc)
2590 if(!pc->prev || !pc->next) {
2591 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2595 /* first remove the pCode from the chain */
2596 pc->prev->next = pc->next;
2597 pc->next->prev = pc->prev;
2599 /* Now for the hard part... */
2601 /* Remove the branches */
2605 pc1 = pb1->pc; /* Get the pCode that branches to the
2606 * one we're unlinking */
2608 /* search for the link back to this pCode (the one we're
2610 if(pb2 = pBranchFind(pc1->to,pc)) {
2611 pb2->pc = pc->to->pc; // make the replacement
2613 /* if the pCode we're unlinking contains multiple 'to'
2614 * branches (e.g. this a skip instruction) then we need
2615 * to copy these extra branches to the chain. */
2617 pBranchAppend(pb2, pc->to->next);
2626 /*-----------------------------------------------------------------*/
2627 /*-----------------------------------------------------------------*/
2629 static void genericAnalyze(pCode *pc)
2639 // Go through the pCodes that are in pCode chain and link
2640 // them together through the pBranches. Note, the pCodes
2641 // are linked together as a contiguous stream like the
2642 // assembly source code lines. The linking here mimics this
2643 // except that comments are not linked in.
2645 pCode *npc = pc->next;
2647 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2648 pBranchLink(pc,npc);
2653 /* reached the end of the pcode chain without finding
2654 * an instruction we could link to. */
2658 fprintf(stderr,"analyze PC_FLOW\n");
2665 /*-----------------------------------------------------------------*/
2666 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2670 if(pc->type == PC_LABEL) {
2671 if( ((pCodeLabel *)pc)->key == pcop_label->key)
2674 if(pc->type == PC_OPCODE) {
2675 pbr = PCI(pc)->label;
2677 if(pbr->pc->type == PC_LABEL) {
2678 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
2688 /*-----------------------------------------------------------------*/
2689 /* findLabel - Search the pCode for a particular label */
2690 /*-----------------------------------------------------------------*/
2691 pCode * findLabel(pCodeOpLabel *pcop_label)
2699 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2700 for(pc = pb->pcHead; pc; pc = pc->next)
2701 if(compareLabel(pc,pcop_label))
2706 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2710 /*-----------------------------------------------------------------*/
2711 /* findNextpCode - given a pCode, find the next of type 'pct' */
2712 /* in the linked list */
2713 /*-----------------------------------------------------------------*/
2714 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2727 /*-----------------------------------------------------------------*/
2728 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
2729 /* in the linked list */
2730 /*-----------------------------------------------------------------*/
2731 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2743 /*-----------------------------------------------------------------*/
2744 /* findNextInstruction - given a pCode, find the next instruction */
2745 /* in the linked list */
2746 /*-----------------------------------------------------------------*/
2747 pCode * findNextInstruction(pCode *pc)
2751 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2757 //fprintf(stderr,"Couldn't find instruction\n");
2761 /*-----------------------------------------------------------------*/
2762 /* findFunctionEnd - given a pCode find the end of the function */
2763 /* that contains it t */
2764 /*-----------------------------------------------------------------*/
2765 pCode * findFunctionEnd(pCode *pc)
2769 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2775 fprintf(stderr,"Couldn't find function end\n");
2780 /*-----------------------------------------------------------------*/
2781 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2782 /* instruction with which it is associated. */
2783 /*-----------------------------------------------------------------*/
2784 static void AnalyzeLabel(pCode *pc)
2793 static void AnalyzeGOTO(pCode *pc)
2796 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2800 static void AnalyzeSKIP(pCode *pc)
2803 pBranchLink(pc,findNextInstruction(pc->next));
2804 pBranchLink(pc,findNextInstruction(pc->next->next));
2808 static void AnalyzeRETURN(pCode *pc)
2811 // branch_link(pc,findFunctionEnd(pc->next));
2817 /*-----------------------------------------------------------------*/
2818 /*-----------------------------------------------------------------*/
2819 regs * getRegFromInstruction(pCode *pc)
2824 PCI(pc)->num_ops == 0 )
2827 switch(PCI(pc)->pcop->type) {
2830 return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2834 fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2835 return PCOR(PCI(pc)->pcop)->r;
2838 fprintf(stderr, "getRegFromInstruction - immediate\n");
2839 return NULL; // PCOR(PCI(pc)->pcop)->r;
2842 return PCOR(PCI(pc)->pcop)->r;
2845 fprintf(stderr, "getRegFromInstruction - dir\n");
2846 //return NULL; PCOR(PCI(pc)->pcop)->r;
2847 return PCOR(PCI(pc)->pcop)->r;
2849 fprintf(stderr, "getRegFromInstruction - literal\n");
2853 fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2854 genericPrint(stderr, pc);
2862 /*-----------------------------------------------------------------*/
2863 /*-----------------------------------------------------------------*/
2865 void AnalyzepBlock(pBlock *pb)
2872 /* Find all of the registers used in this pBlock
2873 * by looking at each instruction and examining it's
2876 for(pc = pb->pcHead; pc; pc = pc->next) {
2878 /* Is this an instruction with operands? */
2879 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2881 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2883 /* Loop through all of the registers declared so far in
2884 this block and see if we find this one there */
2886 regs *r = setFirstItem(pb->tregisters);
2889 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2890 PCOR(PCI(pc)->pcop)->r = r;
2893 r = setNextItem(pb->tregisters);
2897 /* register wasn't found */
2898 r = Safe_calloc(1, sizeof(regs));
2899 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2900 addSet(&pb->tregisters, r);
2901 PCOR(PCI(pc)->pcop)->r = r;
2902 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2904 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2907 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2908 if(PCOR(PCI(pc)->pcop)->r) {
2909 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2910 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2912 if(PCI(pc)->pcop->name)
2913 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2915 fprintf(stderr,"ERROR: NULL register\n");
2924 /*-----------------------------------------------------------------*/
2926 /*-----------------------------------------------------------------*/
2927 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2929 void InsertpFlow(pCode *pc, pCode **pflow)
2931 PCFL(*pflow)->end = pc;
2933 if(!pc || !pc->next)
2936 *pflow = newpCodeFlow();
2937 pCodeInsertAfter(pc, *pflow);
2940 /*-----------------------------------------------------------------*/
2941 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
2942 /* the flow blocks. */
2944 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2945 * point the instruction flow changes.
2947 /*-----------------------------------------------------------------*/
2948 void BuildFlow(pBlock *pb)
2951 pCode *last_pci=NULL;
2958 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
2959 /* Insert a pCodeFlow object at the beginning of a pBlock */
2961 pflow = newpCodeFlow(); /* Create a new Flow object */
2962 pflow->next = pb->pcHead; /* Make the current head the next object */
2963 pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
2964 pb->pcHead = pflow; /* Make the Flow object the head */
2967 for( pc = findNextInstruction(pb->pcHead);
2968 (pc=findNextInstruction(pc)) != NULL; ) {
2971 PCI(pc)->pcflow = PCFL(pflow);
2973 if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
2975 /* The instruction immediately following this one
2976 * marks the beginning of a new flow segment */
2978 InsertpFlow(pc, &pflow);
2981 } else if (PCI_HAS_LABEL(pc)) {
2983 /* This instruction marks the beginning of a
2984 * new flow segment */
2988 InsertpFlow(pc->prev, &pflow);
2990 PCI(pc)->pcflow = PCFL(pflow);
2997 //fprintf (stderr,",end seq %d",GpcFlowSeq);
2998 PCFL(pflow)->end = pb->pcTail;
3001 /*-----------------------------------------------------------------*/
3002 /*-----------------------------------------------------------------*/
3003 void dumpCond(int cond)
3006 static char *pcc_str[] = {
3020 int ncond = sizeof(pcc_str) / sizeof(char *);
3023 fprintf(stderr, "0x%04X\n",cond);
3025 for(i=0,j=1; i<ncond; i++, j<<=1)
3027 fprintf(stderr, " %s\n",pcc_str[i]);
3031 /*-----------------------------------------------------------------*/
3032 /*-----------------------------------------------------------------*/
3033 void FillFlow(pCodeFlow *pcflow)
3042 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3044 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3046 // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3055 int inCond = PCI(pc)->inCond;
3056 int outCond = PCI(pc)->outCond;
3058 if( (reg = getRegFromInstruction(pc)) != NULL) {
3059 if(isSTATUS_REG(reg)) {
3061 //fprintf(stderr, " FillFlow - Status register\n");
3063 /* Check to see if the register banks are changing */
3064 if(PCI(pc)->isModReg) {
3066 pCodeOp *pcop = PCI(pc)->pcop;
3067 switch(PCI(pc)->op) {
3069 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3070 fprintf(stderr, " FillFlow - Set RP0\n");
3071 //outCond |= PCC_REG_BANK1;
3072 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3073 fprintf(stderr, " FillFlow - Set RP1\n");
3074 //outCond |= PCC_REG_BANK3;
3078 if(PCORB(pcop)->bit == PIC_RP0_BIT)
3079 fprintf(stderr, " FillFlow - Clr RP0\n");
3080 //outCond |= PCC_REG_BANK1;
3081 if(PCORB(pcop)->bit == PIC_RP1_BIT)
3082 fprintf(stderr, " FillFlow - Clr RP1\n");
3083 //outCond |= PCC_REG_BANK3;
3087 fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
3088 genericPrint(stderr, pc);
3093 inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
3097 pcflow->inCond |= (inCond & ~pcflow->outCond);
3098 pcflow->outCond |= outCond;
3103 pc = findNextpCode(pc->next, PC_OPCODE);
3104 } while (pc && (pc != pcflow->end));
3108 fprintf(stderr, " FillFlow - Bad end of flow\n");
3111 fprintf(stderr, " FillFlow inCond: ");
3112 dumpCond(pcflow->inCond);
3113 fprintf(stderr, " FillFlow outCond: ");
3114 dumpCond(pcflow->outCond);
3117 /*-----------------------------------------------------------------*/
3118 /*-----------------------------------------------------------------*/
3119 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3122 if(!from || !to || !to->pcflow || !from->pcflow)
3125 addSet(&(from->pcflow->to), to->pcflow);
3126 addSet(&(to->pcflow->from), from->pcflow);
3130 /*-----------------------------------------------------------------*/
3131 /*-----------------------------------------------------------------*/
3132 void LinkFlow(pBlock *pb)
3139 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3140 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3141 pcflow = pcflow->next) {
3144 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3146 //FillFlow(PCFL(pcflow));
3148 pc = PCFL(pcflow)->end;
3150 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3151 if(isPCI_SKIP(pc)) {
3152 //fprintf(stderr, "ends with skip\n");
3153 pct=findNextInstruction(pc->next);
3154 LinkFlow_pCode(PCI(pc),PCI(pct));
3155 pct=findNextInstruction(pct->next);
3156 LinkFlow_pCode(PCI(pc),PCI(pct));
3160 if(isPCI_BRANCH(pc)) {
3161 //fprintf(stderr, "ends with branch\n");
3167 fprintf(stderr, "has an unrecognized ending:\n");
3168 pc->print(stderr,pc);
3171 fprintf(stderr, "has no end pcode\n");
3176 /*-----------------------------------------------------------------*/
3177 /*-----------------------------------------------------------------*/
3178 int OptimizepBlock(pBlock *pb)
3183 if(!pb || !peepOptimizing)
3186 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3187 for(pc = pb->pcHead; pc; pc = pc->next)
3188 matches += pCodePeepMatchRule(pc);
3190 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3195 /*-----------------------------------------------------------------*/
3196 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3197 /*-----------------------------------------------------------------*/
3198 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3202 for(pc = pcs; pc; pc = pc->next) {
3204 if((pc->type == PC_OPCODE) &&
3206 (PCI(pc)->pcop->type == PO_LABEL) &&
3207 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3215 /*-----------------------------------------------------------------*/
3216 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
3217 /* pCode chain if they're not used. */
3218 /*-----------------------------------------------------------------*/
3219 void pBlockRemoveUnusedLabels(pBlock *pb)
3221 pCode *pc; pCodeLabel *pcl;
3226 for(pc = pb->pcHead; pc; pc = pc->next) {
3228 if(pc->type == PC_LABEL)
3230 else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3231 pcl = PCL(PCI(pc)->label->pc);
3234 /* This pCode is a label, so search the pBlock to see if anyone
3237 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3238 /* Couldn't find an instruction that refers to this label
3239 * So, unlink the pCode label from it's pCode chain
3240 * and destroy the label */
3242 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3244 if(pc->type == PC_LABEL) {
3246 pCodeLabelDestruct(pc);
3248 unlinkpCodeFromBranch(pc, PCODE(pcl));
3249 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3260 /*-----------------------------------------------------------------*/
3261 /* pBlockMergeLabels - remove the pCode labels from the pCode */
3262 /* chain and put them into pBranches that are */
3263 /* associated with the appropriate pCode */
3265 /*-----------------------------------------------------------------*/
3266 void pBlockMergeLabels(pBlock *pb)
3269 pCode *pc, *pcnext=NULL;
3274 /* First, Try to remove any unused labels */
3275 //pBlockRemoveUnusedLabels(pb);
3277 /* Now loop through the pBlock and merge the labels with the opcodes */
3279 for(pc = pb->pcHead; pc; pc = pc->next) {
3281 if(pc->type == PC_LABEL) {
3282 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3283 if( !(pcnext = findNextInstruction(pc)) )
3284 return; // Couldn't find an instruction associated with this label
3286 // Unlink the pCode label from it's pCode chain
3289 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3290 // And link it into the instruction's pBranch labels. (Note, since
3291 // it's possible to have multiple labels associated with one instruction
3292 // we must provide a means to accomodate the additional labels. Thus
3293 // the labels are placed into the singly-linked list "label" as
3294 // opposed to being a single member of the pCodeInstruction.)
3296 //_ALLOC(pbr,sizeof(pBranch));
3297 pbr = Safe_calloc(1,sizeof(pBranch));
3301 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3309 pBlockRemoveUnusedLabels(pb);
3313 /*-----------------------------------------------------------------*/
3314 /*-----------------------------------------------------------------*/
3315 void OptimizepCode(char dbName)
3317 #define MAX_PASSES 4
3326 DFPRINTF((stderr," Optimizing pCode\n"));
3329 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3330 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3331 matches += OptimizepBlock(pb);
3334 while(matches && ++passes < MAX_PASSES);
3338 /*-----------------------------------------------------------------*/
3339 /* popCopyGPR2Bit - copy a pcode operator */
3340 /*-----------------------------------------------------------------*/
3342 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3346 pcop = newpCodeOpBit(pc->name, bitval, 0);
3348 if( !( (pcop->type == PO_LABEL) ||
3349 (pcop->type == PO_LITERAL) ||
3350 (pcop->type == PO_STR) ))
3351 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
3359 /*-----------------------------------------------------------------*/
3360 /*-----------------------------------------------------------------*/
3361 int InstructionRegBank(pCode *pc)
3365 if( (reg = getRegFromInstruction(pc)) == NULL)
3368 return REG_BANK(reg);
3373 /*-----------------------------------------------------------------*/
3374 /*-----------------------------------------------------------------*/
3375 void FixRegisterBanking(pBlock *pb)
3387 pc = findNextpCode(pb->pcHead, PC_FLOW);
3390 /* loop through all of the flow blocks with in one pblock */
3392 // fprintf(stderr,"Register banking\n");
3395 /* at this point, pc should point to a PC_FLOW object */
3398 /* for each flow block, determine the register banking
3403 genericPrint(stderr, pc);
3405 reg = getRegFromInstruction(pc);
3408 fprintf(stderr, " %s ",reg->name);
3409 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3413 if(reg && REG_BANK(reg)!=cur_bank) {
3414 /* Examine the instruction before this one to make sure it is
3415 * not a skip type instruction */
3416 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3417 if(pcprev && !isPCI_SKIP(pcprev)) {
3418 int b = cur_bank ^ REG_BANK(reg);
3420 //fprintf(stderr, "Cool! can switch banks\n");
3421 cur_bank = REG_BANK(reg);
3423 new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3424 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3425 pCodeInsertAfter(pc->prev, new_pc);
3426 if(PCI(pc)->label) {
3427 PCI(new_pc)->label = PCI(pc)->label;
3428 PCI(pc)->label = NULL;
3431 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3432 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3433 pCodeInsertAfter(pc, new_pc);
3439 fprintf(stderr, "Bummer can't switch banks\n");
3445 } while(pc && !(isPCFL(pc)));
3447 if(pcprev && cur_bank) {
3448 /* Brute force - make sure that we point to bank 0 at the
3449 * end of each flow block */
3450 new_pc = newpCode(POC_BCF,
3451 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3452 pCodeInsertAfter(pcprev, new_pc);
3460 void pBlockDestruct(pBlock *pb)
3471 /*-----------------------------------------------------------------*/
3472 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3473 /* name dbName and combine them */
3474 /* into one block */
3475 /*-----------------------------------------------------------------*/
3476 void mergepBlocks(char dbName)
3479 pBlock *pb, *pbmerged = NULL,*pbn;
3481 pb = the_pFile->pbHead;
3483 //fprintf(stderr," merging blocks named %c\n",dbName);
3487 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3488 if( getpBlock_dbName(pb) == dbName) {
3490 //fprintf(stderr," merged block %c\n",dbName);
3495 addpCode2pBlock(pbmerged, pb->pcHead);
3496 /* addpCode2pBlock doesn't handle the tail: */
3497 pbmerged->pcTail = pb->pcTail;
3499 pb->prev->next = pbn;
3501 pbn->prev = pb->prev;
3506 //printpBlock(stderr, pbmerged);
3513 /*-----------------------------------------------------------------*/
3514 /* AnalyzeBanking - Called after the memory addresses have been */
3515 /* assigned to the registers. */
3517 /*-----------------------------------------------------------------*/
3518 void AnalyzeBanking(void)
3527 /* Phase 2 - Flow Analysis
3529 * In this phase, the pCode is partition into pCodeFlow
3530 * blocks. The flow blocks mark the points where a continuous
3531 * stream of instructions changes flow (e.g. because of
3532 * a call or goto or whatever).
3535 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3538 /* Phase 2 - Flow Analysis - linking flow blocks
3540 * In this phase, the individual flow blocks are examined
3541 * to determine their order of excution.
3544 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3547 for(pb = the_pFile->pbHead; pb; pb = pb->next)
3548 FixRegisterBanking(pb);
3551 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3553 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3554 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3555 pcflow = pcflow->next) {
3557 FillFlow(PCFL(pcflow));
3564 /*-----------------------------------------------------------------*/
3565 /* buildCallTree - look at the flow and extract all of the calls */
3567 /*-----------------------------------------------------------------*/
3568 set *register_usage(pBlock *pb);
3570 void buildCallTree(void )
3581 /* Now build the call tree.
3582 First we examine all of the pCodes for functions.
3583 Keep in mind that the function boundaries coincide
3584 with pBlock boundaries.
3586 The algorithm goes something like this:
3587 We have two nested loops. The outer loop iterates
3588 through all of the pBlocks/functions. The inner
3589 loop iterates through all of the pCodes for
3590 a given pBlock. When we begin iterating through
3591 a pBlock, the variable pc_fstart, pCode of the start
3592 of a function, is cleared. We then search for pCodes
3593 of type PC_FUNCTION. When one is encountered, we
3594 initialize pc_fstart to this and at the same time
3595 associate a new pBranch object that signifies a
3596 branch entry. If a return is found, then this signifies
3597 a function exit point. We'll link the pCodes of these
3598 returns to the matching pc_fstart.
3600 When we're done, a doubly linked list of pBranches
3601 will exist. The head of this list is stored in
3602 `the_pFile', which is the meta structure for all
3603 of the pCode. Look at the printCallTree function
3604 on how the pBranches are linked together.
3607 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3608 pCode *pc_fstart=NULL;
3609 for(pc = pb->pcHead; pc; pc = pc->next) {
3610 if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
3611 if (PCF(pc)->fname) {
3613 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3614 //fprintf(stderr," found main \n");
3615 pb->cmemmap = NULL; /* FIXME do we need to free ? */
3619 //_ALLOC(pbr,sizeof(pBranch));
3620 pbr = Safe_calloc(1,sizeof(pBranch));
3621 pbr->pc = pc_fstart = pc;
3624 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3626 // Here's a better way of doing the same:
3627 addSet(&pb->function_entries, pc);
3630 // Found an exit point in a function, e.g. return
3631 // (Note, there may be more than one return per function)
3633 pBranchLink(PCF(pc_fstart), PCF(pc));
3635 addSet(&pb->function_exits, pc);
3637 } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3638 addSet(&pb->function_calls,pc);
3643 /* Re-allocate the registers so that there are no collisions
3644 * between local variables when one function call another */
3646 pic14_deallocateAllRegs();
3648 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3655 /*-----------------------------------------------------------------*/
3656 /* AnalyzepCode - parse the pCode that has been generated and form */
3657 /* all of the logical connections. */
3659 /* Essentially what's done here is that the pCode flow is */
3661 /*-----------------------------------------------------------------*/
3663 void AnalyzepCode(char dbName)
3674 /* Phase 1 - Register allocation and peep hole optimization
3676 * The first part of the analysis is to determine the registers
3677 * that are used in the pCode. Once that is done, the peep rules
3678 * are applied to the code. We continue to loop until no more
3679 * peep rule optimizations are found (or until we exceed the
3680 * MAX_PASSES threshold).
3682 * When done, the required registers will be determined.
3688 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3690 /* First, merge the labels with the instructions */
3691 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3692 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3694 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3695 //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3696 pBlockMergeLabels(pb);
3703 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3704 if('*' == dbName || getpBlock_dbName(pb) == dbName)
3705 changes += OptimizepBlock(pb);
3708 } while(changes && (i++ < MAX_PASSES));
3713 /*-----------------------------------------------------------------*/
3714 /* ispCodeFunction - returns true if *pc is the pCode of a */
3716 /*-----------------------------------------------------------------*/
3717 bool ispCodeFunction(pCode *pc)
3720 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3726 /*-----------------------------------------------------------------*/
3727 /* findFunction - Search for a function by name (given the name) */
3728 /* in the set of all functions that are in a pBlock */
3729 /* (note - I expect this to change because I'm planning to limit */
3730 /* pBlock's to just one function declaration */
3731 /*-----------------------------------------------------------------*/
3732 pCode *findFunction(char *fname)
3739 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3741 pc = setFirstItem(pb->function_entries);
3744 if((pc->type == PC_FUNCTION) &&
3746 (strcmp(fname, PCF(pc)->fname)==0))
3749 pc = setNextItem(pb->function_entries);
3757 void MarkUsedRegisters(set *regset)
3762 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3763 r2 = pic14_regWithIdx(r1->rIdx);
3769 void pBlockStats(FILE *of, pBlock *pb)
3775 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3777 // for now just print the first element of each set
3778 pc = setFirstItem(pb->function_entries);
3780 fprintf(of,";entry: ");
3783 pc = setFirstItem(pb->function_exits);
3785 fprintf(of,";has an exit\n");
3789 pc = setFirstItem(pb->function_calls);
3791 fprintf(of,";functions called:\n");
3794 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3795 fprintf(of,"; %s\n",get_op(PCI(pc)));
3797 pc = setNextItem(pb->function_calls);
3801 r = setFirstItem(pb->tregisters);
3803 int n = elementsInSet(pb->tregisters);
3805 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3808 fprintf(of,"; %s\n",r->name);
3809 r = setNextItem(pb->tregisters);
3814 /*-----------------------------------------------------------------*/
3815 /*-----------------------------------------------------------------*/
3816 static void sequencepCode(void)
3822 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3824 pb->seq = GpCodeSequenceNumber+1;
3826 for( pc = pb->pcHead; pc; pc = pc->next)
3827 pc->seq = ++GpCodeSequenceNumber;
3832 /*-----------------------------------------------------------------*/
3833 /*-----------------------------------------------------------------*/
3834 set *register_usage(pBlock *pb)
3837 set *registers=NULL;
3838 set *registersInCallPath = NULL;
3840 /* check recursion */
3842 pc = setFirstItem(pb->function_entries);
3849 if(pc->type != PC_FUNCTION)
3850 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3852 pc = setFirstItem(pb->function_calls);
3853 for( ; pc; pc = setNextItem(pb->function_calls)) {
3855 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3856 char *dest = get_op(PCI(pc));
3858 pcn = findFunction(dest);
3860 registersInCallPath = register_usage(pcn->pb);
3862 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3867 pBlockStats(stderr,pb); // debug
3870 // Mark the registers in this block as used.
3872 MarkUsedRegisters(pb->tregisters);
3873 if(registersInCallPath) {
3874 /* registers were used in the functions this pBlock has called */
3875 /* so now, we need to see if these collide with the ones we are */
3878 regs *r1,*r2, *newreg;
3880 DFPRINTF((stderr,"comparing registers\n"));
3882 r1 = setFirstItem(registersInCallPath);
3885 r2 = setFirstItem(pb->tregisters);
3887 while(r2 && (r1->type != REG_STK)) {
3889 if(r2->rIdx == r1->rIdx) {
3890 newreg = pic14_findFreeReg(REG_GPR);
3894 DFPRINTF((stderr,"Bummer, no more registers.\n"));
3898 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3899 r1->rIdx, newreg->rIdx));
3900 r2->rIdx = newreg->rIdx;
3901 //if(r2->name) free(r2->name);
3903 r2->name = Safe_strdup(newreg->name);
3907 newreg->wasUsed = 1;
3909 r2 = setNextItem(pb->tregisters);
3912 r1 = setNextItem(registersInCallPath);
3915 /* Collisions have been resolved. Now free the registers in the call path */
3916 r1 = setFirstItem(registersInCallPath);
3918 if(r1->type != REG_STK) {
3919 newreg = pic14_regWithIdx(r1->rIdx);
3922 r1 = setNextItem(registersInCallPath);
3926 // MarkUsedRegisters(pb->registers);
3928 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3931 DFPRINTF((stderr,"returning regs\n"));
3933 DFPRINTF((stderr,"not returning regs\n"));
3935 DFPRINTF((stderr,"pBlock after register optim.\n"));
3936 pBlockStats(stderr,pb); // debug
3942 /*-----------------------------------------------------------------*/
3943 /* printCallTree - writes the call tree to a file */
3945 /*-----------------------------------------------------------------*/
3946 void pct2(FILE *of,pBlock *pb,int indent)
3950 // set *registersInCallPath = NULL;
3953 return;// registers;
3956 return; // registers; //recursion ?
3958 pc = setFirstItem(pb->function_entries);
3965 for(i=0;i<indent;i++) // Indentation
3968 if(pc->type == PC_FUNCTION)
3969 fprintf(of,"%s\n",PCF(pc)->fname);
3974 pc = setFirstItem(pb->function_calls);
3975 for( ; pc; pc = setNextItem(pb->function_calls)) {
3977 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3978 char *dest = get_op(PCI(pc));
3980 pcn = findFunction(dest);
3982 pct2(of,pcn->pb,indent+1);
3984 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3992 fprintf(stderr,"pBlock before register optim.\n");
3993 pBlockStats(stderr,pb); // debug
3995 if(registersInCallPath) {
3996 /* registers were used in the functions this pBlock has called */
3997 /* so now, we need to see if these collide with the ones we are using here */
3999 regs *r1,*r2, *newreg;
4001 fprintf(stderr,"comparing registers\n");
4003 r1 = setFirstItem(registersInCallPath);
4006 r2 = setFirstItem(pb->registers);
4010 if(r2->rIdx == r1->rIdx) {
4011 newreg = pic14_findFreeReg();
4015 fprintf(stderr,"Bummer, no more registers.\n");
4019 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
4020 r1->rIdx, newreg->rIdx);
4021 r2->rIdx = newreg->rIdx;
4022 //if(r2->name) free(r2->name);
4024 r2->name = Safe_strdup(newreg->name);
4028 newreg->wasUsed = 1;
4030 r2 = setNextItem(pb->registers);
4033 r1 = setNextItem(registersInCallPath);
4036 /* Collisions have been resolved. Now free the registers in the call path */
4037 r1 = setFirstItem(registersInCallPath);
4039 newreg = pic14_regWithIdx(r1->rIdx);
4041 r1 = setNextItem(registersInCallPath);
4045 MarkUsedRegisters(pb->registers);
4047 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
4050 fprintf(stderr,"returning regs\n");
4052 fprintf(stderr,"not returning regs\n");
4054 fprintf(stderr,"pBlock after register optim.\n");
4055 pBlockStats(stderr,pb); // debug
4063 /*-----------------------------------------------------------------*/
4064 /* printCallTree - writes the call tree to a file */
4066 /*-----------------------------------------------------------------*/
4068 void printCallTree(FILE *of)
4080 fprintf(of, "\npBlock statistics\n");
4081 for(pb = the_pFile->pbHead; pb; pb = pb->next )
4086 fprintf(of,"Call Tree\n");
4087 pbr = the_pFile->functions;
4091 if(!ispCodeFunction(pc))
4092 fprintf(of,"bug in call tree");
4095 fprintf(of,"Function: %s\n", PCF(pc)->fname);
4097 while(pc->next && !ispCodeFunction(pc->next)) {
4099 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4100 fprintf(of,"\t%s\n",get_op(PCI(pc)));
4108 /* Re-allocate the registers so that there are no collisions
4109 * between local variables when one function call another */
4111 pic14_deallocateAllRegs();
4113 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4119 fprintf(of,"\n**************\n\na better call tree\n");
4120 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4125 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4126 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));