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 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1; /* inline functions if nonzero */
80 int debug_verbose = 0; /* Set true to inundate .asm file */
82 // static int GpCodeSequenceNumber = 1;
85 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
86 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
88 extern void RemoveUnusedRegisters(void);
89 extern void RegsUnMapLiveRanges(void);
90 extern void BuildFlowTree(pBlock *pb);
91 extern void pCodeRegOptimizeRegUsage(int level);
92 extern int picIsInitialized(void);
93 extern const char *pCodeOpType(pCodeOp *pcop);
95 /****************************************************************/
96 /* Forward declarations */
97 /****************************************************************/
99 void unlinkpCode(pCode *pc);
101 static void genericAnalyze(pCode *pc);
102 static void AnalyzeGOTO(pCode *pc);
103 static void AnalyzeSKIP(pCode *pc);
104 static void AnalyzeRETURN(pCode *pc);
107 static void genericDestruct(pCode *pc);
108 static void genericPrint(FILE *of,pCode *pc);
110 static void pCodePrintLabel(FILE *of, pCode *pc);
111 static void pCodePrintFunction(FILE *of, pCode *pc);
112 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
113 static char *get_op_from_instruction( pCodeInstruction *pcc);
114 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
115 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
116 int pCodePeepMatchRule(pCode *pc);
117 void pBlockStats(FILE *of, pBlock *pb);
118 pBlock *newpBlock(void);
119 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
120 void pCodeRegMapLiveRanges(pBlock *pb);
123 /****************************************************************/
124 /* PIC Instructions */
125 /****************************************************************/
127 pCodeInstruction pciADDWF = {
128 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
141 1,0, // dest, bit instruction
143 0, // literal operand
145 (PCC_W | PCC_REGISTER), // inCond
146 (PCC_REGISTER | PCC_Z) // outCond
149 pCodeInstruction pciADDFW = {
150 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
163 0,0, // dest, bit instruction
165 0, // literal operand
167 (PCC_W | PCC_REGISTER), // inCond
168 (PCC_W | PCC_Z) // outCond
171 pCodeInstruction pciADDLW = {
172 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
185 0,0, // dest, bit instruction
187 1, // literal operand
189 (PCC_W | PCC_LITERAL), // inCond
190 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
193 pCodeInstruction pciANDLW = {
194 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
207 0,0, // dest, bit instruction
209 1, // literal operand
211 (PCC_W | PCC_LITERAL), // inCond
212 (PCC_W | PCC_Z) // outCond
215 pCodeInstruction pciANDWF = {
216 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
229 1,0, // dest, bit instruction
231 0, // literal operand
233 (PCC_W | PCC_REGISTER), // inCond
234 (PCC_REGISTER | PCC_Z) // outCond
237 pCodeInstruction pciANDFW = {
238 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
251 0,0, // dest, bit instruction
253 0, // literal operand
255 (PCC_W | PCC_REGISTER), // inCond
256 (PCC_W | PCC_Z) // outCond
259 pCodeInstruction pciBCF = {
260 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
273 1,1, // dest, bit instruction
275 0, // literal operand
277 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
278 PCC_REGISTER // outCond
281 pCodeInstruction pciBSF = {
282 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
295 1,1, // dest, bit instruction
297 0, // literal operand
299 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
300 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
303 pCodeInstruction pciBTFSC = {
304 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
317 0,1, // dest, bit instruction
319 0, // literal operand
321 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
322 PCC_EXAMINE_PCOP // outCond
325 pCodeInstruction pciBTFSS = {
326 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
339 0,1, // dest, bit instruction
341 0, // literal operand
343 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
344 PCC_EXAMINE_PCOP // outCond
347 pCodeInstruction pciCALL = {
348 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
361 0,0, // dest, bit instruction
363 0, // literal operand
369 pCodeInstruction pciCOMF = {
370 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
383 1,0, // dest, bit instruction
385 0, // literal operand
387 PCC_REGISTER, // inCond
388 PCC_REGISTER // outCond
391 pCodeInstruction pciCOMFW = {
392 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
405 0,0, // dest, bit instruction
407 0, // literal operand
409 PCC_REGISTER, // inCond
413 pCodeInstruction pciCLRF = {
414 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
427 0,0, // dest, bit instruction
429 0, // literal operand
432 PCC_REGISTER // outCond
435 pCodeInstruction pciCLRW = {
436 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
449 0,0, // dest, bit instruction
451 0, // literal operand
457 pCodeInstruction pciCLRWDT = {
458 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
471 0,0, // dest, bit instruction
473 0, // literal operand
479 pCodeInstruction pciDECF = {
480 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
493 1,0, // dest, bit instruction
495 0, // literal operand
497 PCC_REGISTER, // inCond
498 PCC_REGISTER // outCond
501 pCodeInstruction pciDECFW = {
502 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
515 0,0, // dest, bit instruction
517 0, // literal operand
519 PCC_REGISTER, // inCond
523 pCodeInstruction pciDECFSZ = {
524 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
537 1,0, // dest, bit instruction
539 0, // literal operand
541 PCC_REGISTER, // inCond
542 PCC_REGISTER // outCond
545 pCodeInstruction pciDECFSZW = {
546 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
559 0,0, // dest, bit instruction
561 0, // literal operand
563 PCC_REGISTER, // inCond
567 pCodeInstruction pciGOTO = {
568 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
581 0,0, // dest, bit instruction
583 0, // literal operand
589 pCodeInstruction pciINCF = {
590 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
603 1,0, // dest, bit instruction
605 0, // literal operand
607 PCC_REGISTER, // inCond
608 PCC_REGISTER // outCond
611 pCodeInstruction pciINCFW = {
612 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
625 0,0, // dest, bit instruction
627 0, // literal operand
629 PCC_REGISTER, // inCond
633 pCodeInstruction pciINCFSZ = {
634 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
647 1,0, // dest, bit instruction
649 0, // literal operand
651 PCC_REGISTER, // inCond
652 PCC_REGISTER // outCond
655 pCodeInstruction pciINCFSZW = {
656 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
669 0,0, // dest, bit instruction
671 0, // literal operand
673 PCC_REGISTER, // inCond
677 pCodeInstruction pciIORWF = {
678 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
691 1,0, // dest, bit instruction
693 0, // literal operand
695 (PCC_W | PCC_REGISTER), // inCond
696 (PCC_REGISTER | PCC_Z) // outCond
699 pCodeInstruction pciIORFW = {
700 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
713 0,0, // dest, bit instruction
715 0, // literal operand
717 (PCC_W | PCC_REGISTER), // inCond
718 (PCC_W | PCC_Z) // outCond
721 pCodeInstruction pciIORLW = {
722 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
735 0,0, // dest, bit instruction
737 1, // literal operand
739 (PCC_W | PCC_LITERAL), // inCond
740 (PCC_W | PCC_Z) // outCond
743 pCodeInstruction pciMOVF = {
744 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
757 1,0, // dest, bit instruction
759 0, // literal operand
761 PCC_REGISTER, // inCond
765 pCodeInstruction pciMOVFW = {
766 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
779 0,0, // dest, bit instruction
781 0, // literal operand
783 PCC_REGISTER, // inCond
784 (PCC_W | PCC_Z) // outCond
787 pCodeInstruction pciMOVWF = {
788 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
801 0,0, // dest, bit instruction
803 0, // literal operand
806 PCC_REGISTER // outCond
809 pCodeInstruction pciMOVLW = {
810 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
822 0,0, // dest, bit instruction
824 1, // literal operand
826 (PCC_NONE | PCC_LITERAL), // inCond
830 pCodeInstruction pciNOP = {
831 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
843 0,0, // dest, bit instruction
845 0, // literal operand
851 pCodeInstruction pciRETFIE = {
852 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
870 PCC_NONE // outCond (not true... affects the GIE bit too)
873 pCodeInstruction pciRETLW = {
874 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
887 0,0, // dest, bit instruction
889 1, // literal operand
891 PCC_LITERAL, // inCond
895 pCodeInstruction pciRETURN = {
896 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
909 0,0, // dest, bit instruction
911 0, // literal operand
917 pCodeInstruction pciRLF = {
918 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
931 1,0, // dest, bit instruction
933 0, // literal operand
935 (PCC_C | PCC_REGISTER), // inCond
936 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
939 pCodeInstruction pciRLFW = {
940 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
953 0,0, // dest, bit instruction
955 0, // literal operand
957 (PCC_C | PCC_REGISTER), // inCond
958 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
961 pCodeInstruction pciRRF = {
962 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
975 1,0, // dest, bit instruction
977 0, // literal operand
979 (PCC_C | PCC_REGISTER), // inCond
980 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
983 pCodeInstruction pciRRFW = {
984 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
997 0,0, // dest, bit instruction
999 0, // literal operand
1001 (PCC_C | PCC_REGISTER), // inCond
1002 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1005 pCodeInstruction pciSUBWF = {
1006 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1012 NULL, // from branch
1019 1,0, // dest, bit instruction
1020 0,0, // branch, skip
1021 0, // literal operand
1023 (PCC_W | PCC_REGISTER), // inCond
1024 (PCC_REGISTER | PCC_Z) // outCond
1027 pCodeInstruction pciSUBFW = {
1028 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1034 NULL, // from branch
1041 0,0, // dest, bit instruction
1042 0,0, // branch, skip
1043 0, // literal operand
1045 (PCC_W | PCC_REGISTER), // inCond
1046 (PCC_W | PCC_Z) // outCond
1049 pCodeInstruction pciSUBLW = {
1050 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1056 NULL, // from branch
1063 0,0, // dest, bit instruction
1064 0,0, // branch, skip
1065 1, // literal operand
1067 (PCC_W | PCC_LITERAL), // inCond
1068 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1071 pCodeInstruction pciSWAPF = {
1072 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1078 NULL, // from branch
1085 1,0, // dest, bit instruction
1086 0,0, // branch, skip
1087 0, // literal operand
1089 (PCC_REGISTER), // inCond
1090 (PCC_REGISTER) // outCond
1093 pCodeInstruction pciSWAPFW = {
1094 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1100 NULL, // from branch
1107 0,0, // dest, bit instruction
1108 0,0, // branch, skip
1109 0, // literal operand
1111 (PCC_REGISTER), // inCond
1115 pCodeInstruction pciTRIS = {
1116 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1122 NULL, // from branch
1129 0,0, // dest, bit instruction
1130 0,0, // branch, skip
1131 0, // literal operand
1134 PCC_REGISTER // outCond
1137 pCodeInstruction pciXORWF = {
1138 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1144 NULL, // from branch
1151 1,0, // dest, bit instruction
1152 0,0, // branch, skip
1153 0, // literal operand
1155 (PCC_W | PCC_REGISTER), // inCond
1156 (PCC_REGISTER | PCC_Z) // outCond
1159 pCodeInstruction pciXORFW = {
1160 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1166 NULL, // from branch
1173 0,0, // dest, bit instruction
1174 0,0, // branch, skip
1175 0, // literal operand
1177 (PCC_W | PCC_REGISTER), // inCond
1178 (PCC_W | PCC_Z) // outCond
1181 pCodeInstruction pciXORLW = {
1182 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1188 NULL, // from branch
1195 0,0, // dest, bit instruction
1196 0,0, // branch, skip
1197 1, // literal operand
1199 (PCC_W | PCC_LITERAL), // inCond
1200 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1204 pCodeInstruction pciBANKSEL = {
1205 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1211 NULL, // from branch
1218 0,0, // dest, bit instruction
1219 0,0, // branch, skip
1220 0, // literal operand
1223 PCC_REGISTER // outCond
1226 pCodeInstruction pciPAGESEL = {
1227 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1233 NULL, // from branch
1240 0,0, // dest, bit instruction
1241 0,0, // branch, skip
1242 0, // literal operand
1245 PCC_REGISTER // outCond
1248 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1251 /*-----------------------------------------------------------------*/
1252 /* return a unique ID number to assist pCodes debuging */
1253 /*-----------------------------------------------------------------*/
1254 unsigned PCodeID(void) {
1255 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1257 static unsigned int stop;
1259 stop++; // Place break point here
1264 #ifdef HAVE_VSNPRINTF
1265 // Alas, vsnprintf is not ANSI standard, and does not exist
1266 // on Solaris (and probably other non-Gnu flavored Unixes).
1268 /*-----------------------------------------------------------------*/
1269 /* SAFE_snprintf - like snprintf except the string pointer is */
1270 /* after the string has been printed to. This is */
1271 /* useful for printing to string as though if it */
1272 /* were a stream. */
1273 /*-----------------------------------------------------------------*/
1274 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1282 va_start(val, format);
1284 vsnprintf(*str, *size, format, val);
1289 if((size_t)len > *size) {
1290 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1291 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1299 #else // HAVE_VSNPRINTF
1301 // This version is *not* safe, despite the name.
1303 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1307 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1312 va_start(val, format);
1314 vsprintf(buffer, format, val);
1317 len = strlen(buffer);
1319 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1320 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1323 strcpy(*str, buffer);
1329 #endif // HAVE_VSNPRINTF
1332 extern void initStack(int base_address, int size);
1333 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1334 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1335 extern void init_pic(char *);
1337 void pCodeInitRegisters(void)
1339 static int initialized=0;
1340 int shareBankAddress,stkSize;
1346 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1347 stkSize = 8; // Set pseudo stack size to 8
1348 initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters
1349 init_pic(port->processor);
1351 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1352 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1353 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1354 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1355 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1356 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1358 pc_status.rIdx = IDX_STATUS;
1359 pc_fsr.rIdx = IDX_FSR;
1360 pc_indf.rIdx = IDX_INDF;
1361 pc_intcon.rIdx = IDX_INTCON;
1362 pc_pcl.rIdx = IDX_PCL;
1363 pc_pclath.rIdx = IDX_PCLATH;
1365 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1366 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1367 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1369 pc_wsave.rIdx = pc_wsave.r->rIdx;
1370 pc_ssave.rIdx = pc_ssave.r->rIdx;
1371 pc_psave.rIdx = pc_psave.r->rIdx;
1373 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1374 pc_wsave.r->address = shareBankAddress-stkSize;
1375 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1376 pc_ssave.r->address = shareBankAddress-stkSize-1;
1377 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1378 pc_psave.r->address = shareBankAddress-stkSize-2;
1380 /* probably should put this in a separate initialization routine */
1381 pb_dead_pcodes = newpBlock();
1385 /*-----------------------------------------------------------------*/
1386 /* mnem2key - convert a pic mnemonic into a hash key */
1387 /* (BTW - this spreads the mnemonics quite well) */
1389 /*-----------------------------------------------------------------*/
1391 int mnem2key(char const *mnem)
1400 key += toupper(*mnem++) +1;
1404 return (key & 0x1f);
1408 void pic14initMnemonics(void)
1413 pCodeInstruction *pci;
1415 if(mnemonics_initialized)
1418 //FIXME - probably should NULL out the array before making the assignments
1419 //since we check the array contents below this initialization.
1421 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1422 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1423 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1424 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1425 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1426 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1427 pic14Mnemonics[POC_BCF] = &pciBCF;
1428 pic14Mnemonics[POC_BSF] = &pciBSF;
1429 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1430 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1431 pic14Mnemonics[POC_CALL] = &pciCALL;
1432 pic14Mnemonics[POC_COMF] = &pciCOMF;
1433 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1434 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1435 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1436 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1437 pic14Mnemonics[POC_DECF] = &pciDECF;
1438 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1439 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1440 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1441 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1442 pic14Mnemonics[POC_INCF] = &pciINCF;
1443 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1444 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1445 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1446 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1447 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1448 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1449 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1450 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1451 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1452 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1453 pic14Mnemonics[POC_NOP] = &pciNOP;
1454 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1455 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1456 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1457 pic14Mnemonics[POC_RLF] = &pciRLF;
1458 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1459 pic14Mnemonics[POC_RRF] = &pciRRF;
1460 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1461 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1462 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1463 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1464 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1465 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1466 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1467 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1468 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1469 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1470 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1471 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1473 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1474 if(pic14Mnemonics[i])
1475 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1476 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1479 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1480 pci = hTabNextItem(pic14MnemonicsHash, &key);
1483 mnemonics_initialized = 1;
1486 int getpCodePeepCommand(char *cmd);
1488 int getpCode(char *mnem,unsigned dest)
1491 pCodeInstruction *pci;
1492 int key = mnem2key(mnem);
1494 if(!mnemonics_initialized)
1495 pic14initMnemonics();
1497 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1501 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1502 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1506 pci = hTabNextItemWK (pic14MnemonicsHash);
1513 /*-----------------------------------------------------------------*
1514 * pic14initpCodePeepCommands
1516 *-----------------------------------------------------------------*/
1517 void pic14initpCodePeepCommands(void)
1525 hTabAddItem(&pic14pCodePeepCommandsHash,
1526 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1528 } while (peepCommands[i].cmd);
1530 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1533 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1534 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1539 /*-----------------------------------------------------------------
1542 *-----------------------------------------------------------------*/
1544 int getpCodePeepCommand(char *cmd)
1548 int key = mnem2key(cmd);
1551 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1554 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1555 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1559 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1566 char getpBlock_dbName(pBlock *pb)
1572 return pb->cmemmap->dbName;
1576 void pBlockConvert2ISR(pBlock *pb)
1587 /*-----------------------------------------------------------------*/
1588 /* movepBlock2Head - given the dbname of a pBlock, move all */
1589 /* instances to the front of the doubly linked */
1590 /* list of pBlocks */
1591 /*-----------------------------------------------------------------*/
1593 void movepBlock2Head(char dbName)
1600 pb = the_pFile->pbHead;
1604 if(getpBlock_dbName(pb) == dbName) {
1605 pBlock *pbn = pb->next;
1606 pb->next = the_pFile->pbHead;
1607 the_pFile->pbHead->prev = pb;
1608 the_pFile->pbHead = pb;
1611 pb->prev->next = pbn;
1613 // If the pBlock that we just moved was the last
1614 // one in the link of all of the pBlocks, then we
1615 // need to point the tail to the block just before
1616 // the one we moved.
1617 // Note: if pb->next is NULL, then pb must have
1618 // been the last pBlock in the chain.
1621 pbn->prev = pb->prev;
1623 the_pFile->pbTail = pb->prev;
1634 void copypCode(FILE *of, char dbName)
1638 if(!of || !the_pFile)
1641 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1642 if(getpBlock_dbName(pb) == dbName) {
1650 void pcode_test(void)
1653 DFPRINTF((stderr,"pcode is alive!\n"));
1663 /* create the file name */
1664 strcpy(buffer,dstFileName);
1665 strcat(buffer,".p");
1667 if( !(pFile = fopen(buffer, "w" ))) {
1668 werror(E_FILE_OPEN_ERR,buffer);
1672 fprintf(pFile,"pcode dump\n\n");
1674 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1675 fprintf(pFile,"\n\tNew pBlock\n\n");
1677 fprintf(pFile,"%s",pb->cmemmap->sname);
1679 fprintf(pFile,"internal pblock");
1681 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1682 printpBlock(pFile,pb);
1686 /*-----------------------------------------------------------------*/
1687 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1688 /* ister, RegCond will return the bit being referenced. */
1690 /* fixme - why not just OR in the pcop bit field */
1691 /*-----------------------------------------------------------------*/
1693 static int RegCond(pCodeOp *pcop)
1699 if (pcop->type == PO_GPR_BIT) {
1700 char *name = pcop->name;
1702 name = PCOR(pcop)->r->name;
1703 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1704 switch(PCORB(pcop)->bit) {
1718 /*-----------------------------------------------------------------*/
1719 /* newpCode - create and return a newly initialized pCode */
1721 /* fixme - rename this */
1723 /* The purpose of this routine is to create a new Instruction */
1724 /* pCode. This is called by gen.c while the assembly code is being */
1728 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1729 /* (note that the op is analogous to but not the */
1730 /* same thing as the opcode of the instruction.) */
1731 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1734 /* a pointer to the new malloc'd pCode is returned. */
1738 /*-----------------------------------------------------------------*/
1739 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1741 pCodeInstruction *pci ;
1743 if(!mnemonics_initialized)
1744 pic14initMnemonics();
1746 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1748 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1749 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1750 pci->pc.id = PCodeID();
1753 if(pci->inCond & PCC_EXAMINE_PCOP)
1754 pci->inCond |= RegCond(pcop);
1756 if(pci->outCond & PCC_EXAMINE_PCOP)
1757 pci->outCond |= RegCond(pcop);
1759 pci->pc.prev = pci->pc.next = NULL;
1760 return (pCode *)pci;
1763 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1769 /*-----------------------------------------------------------------*/
1770 /* newpCodeWild - create a "wild" as in wild card pCode */
1772 /* Wild pcodes are used during the peep hole optimizer to serve */
1773 /* as place holders for any instruction. When a snippet of code is */
1774 /* compared to a peep hole rule, the wild card opcode will match */
1775 /* any instruction. However, the optional operand and label are */
1776 /* additional qualifiers that must also be matched before the */
1777 /* line (of assembly code) is declared matched. Note that the */
1778 /* operand may be wild too. */
1780 /* Note, a wild instruction is specified just like a wild var: */
1781 /* %4 ; A wild instruction, */
1782 /* See the peeph.def file for additional examples */
1784 /*-----------------------------------------------------------------*/
1786 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1791 pcw = Safe_calloc(1,sizeof(pCodeWild));
1793 pcw->pci.pc.type = PC_WILD;
1794 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1795 pcw->id = PCodeID();
1796 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1797 pcw->pci.pc.pb = NULL;
1799 // pcw->pci.pc.analyze = genericAnalyze;
1800 pcw->pci.pc.destruct = genericDestruct;
1801 pcw->pci.pc.print = genericPrint;
1803 pcw->id = pCodeID; // this is the 'n' in %n
1804 pcw->operand = optional_operand;
1805 pcw->label = optional_label;
1807 pcw->mustBeBitSkipInst = 0;
1808 pcw->mustNotBeBitSkipInst = 0;
1809 pcw->invertBitSkipInst = 0;
1811 return ( (pCode *)pcw);
1815 /*-----------------------------------------------------------------*/
1816 /* newPcodeInlineP - create a new pCode from a char string */
1817 /*-----------------------------------------------------------------*/
1820 pCode *newpCodeInlineP(char *cP)
1825 pcc = Safe_calloc(1,sizeof(pCodeComment));
1827 pcc->pc.type = PC_INLINE;
1828 pcc->pc.prev = pcc->pc.next = NULL;
1829 pcc->pc.id = PCodeID();
1830 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1833 // pcc->pc.analyze = genericAnalyze;
1834 pcc->pc.destruct = genericDestruct;
1835 pcc->pc.print = genericPrint;
1838 pcc->comment = Safe_strdup(cP);
1840 pcc->comment = NULL;
1842 return ( (pCode *)pcc);
1846 /*-----------------------------------------------------------------*/
1847 /* newPcodeCharP - create a new pCode from a char string */
1848 /*-----------------------------------------------------------------*/
1850 pCode *newpCodeCharP(char *cP)
1855 pcc = Safe_calloc(1,sizeof(pCodeComment));
1857 pcc->pc.type = PC_COMMENT;
1858 pcc->pc.prev = pcc->pc.next = NULL;
1859 pcc->pc.id = PCodeID();
1860 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1863 // pcc->pc.analyze = genericAnalyze;
1864 pcc->pc.destruct = genericDestruct;
1865 pcc->pc.print = genericPrint;
1868 pcc->comment = Safe_strdup(cP);
1870 pcc->comment = NULL;
1872 return ( (pCode *)pcc);
1876 /*-----------------------------------------------------------------*/
1877 /* newpCodeFunction - */
1878 /*-----------------------------------------------------------------*/
1881 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1885 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1886 //_ALLOC(pcf,sizeof(pCodeFunction));
1888 pcf->pc.type = PC_FUNCTION;
1889 pcf->pc.prev = pcf->pc.next = NULL;
1890 pcf->pc.id = PCodeID();
1891 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1894 // pcf->pc.analyze = genericAnalyze;
1895 pcf->pc.destruct = genericDestruct;
1896 pcf->pc.print = pCodePrintFunction;
1901 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1902 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1903 strcpy(pcf->modname,mod);
1905 pcf->modname = NULL;
1908 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1909 pcf->fname = Safe_calloc(1,strlen(f)+1);
1910 strcpy(pcf->fname,f);
1914 pcf->isPublic = (unsigned)isPublic;
1916 return ( (pCode *)pcf);
1920 /*-----------------------------------------------------------------*/
1922 /*-----------------------------------------------------------------*/
1923 void destructpCodeFlow(pCode *pc)
1925 if(!pc || !isPCFL(pc))
1934 deleteSet(&PCFL(pc)->registers);
1935 deleteSet(&PCFL(pc)->from);
1936 deleteSet(&PCFL(pc)->to);
1941 pCode *newpCodeFlow(void )
1945 //_ALLOC(pcflow,sizeof(pCodeFlow));
1946 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1948 pcflow->pc.type = PC_FLOW;
1949 pcflow->pc.prev = pcflow->pc.next = NULL;
1950 pcflow->pc.pb = NULL;
1952 // pcflow->pc.analyze = genericAnalyze;
1953 pcflow->pc.destruct = destructpCodeFlow;
1954 pcflow->pc.print = genericPrint;
1956 pcflow->pc.seq = GpcFlowSeq++;
1958 pcflow->from = pcflow->to = NULL;
1960 pcflow->inCond = PCC_NONE;
1961 pcflow->outCond = PCC_NONE;
1963 pcflow->firstBank = 'U'; /* Undetermined */
1964 pcflow->lastBank = 'U'; /* Undetermined */
1966 pcflow->FromConflicts = 0;
1967 pcflow->ToConflicts = 0;
1971 pcflow->registers = newSet();
1973 return ( (pCode *)pcflow);
1977 /*-----------------------------------------------------------------*/
1978 /*-----------------------------------------------------------------*/
1979 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1981 pCodeFlowLink *pcflowLink;
1983 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1985 pcflowLink->pcflow = pcflow;
1986 pcflowLink->bank_conflict = 0;
1991 /*-----------------------------------------------------------------*/
1992 /* newpCodeCSource - create a new pCode Source Symbol */
1993 /*-----------------------------------------------------------------*/
1995 pCode *newpCodeCSource(int ln, char *f, char *l)
2000 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2002 pccs->pc.type = PC_CSOURCE;
2003 pccs->pc.prev = pccs->pc.next = NULL;
2004 pccs->pc.id = PCodeID();
2007 pccs->pc.destruct = genericDestruct;
2008 pccs->pc.print = genericPrint;
2010 pccs->line_number = ln;
2012 pccs->line = Safe_strdup(l);
2017 pccs->file_name = Safe_strdup(f);
2019 pccs->file_name = NULL;
2021 return ( (pCode *)pccs);
2024 /*-----------------------------------------------------------------*/
2025 /* pCodeLabelDestruct - free memory used by a label. */
2026 /*-----------------------------------------------------------------*/
2027 static void pCodeLabelDestruct(pCode *pc)
2033 if((pc->type == PC_LABEL) && PCL(pc)->label)
2034 free(PCL(pc)->label);
2040 pCode *newpCodeLabel(char *name, int key)
2046 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2048 pcl->pc.type = PC_LABEL;
2049 pcl->pc.prev = pcl->pc.next = NULL;
2050 pcl->pc.id = PCodeID();
2051 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2054 // pcl->pc.analyze = genericAnalyze;
2055 pcl->pc.destruct = pCodeLabelDestruct;
2056 pcl->pc.print = pCodePrintLabel;
2062 sprintf(s,"_%05d_DS_",key);
2067 pcl->label = Safe_strdup(s);
2069 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2070 return ( (pCode *)pcl);
2075 /*-----------------------------------------------------------------*/
2076 /* newpBlock - create and return a pointer to a new pBlock */
2077 /*-----------------------------------------------------------------*/
2078 pBlock *newpBlock(void)
2083 PpB = Safe_calloc(1,sizeof(pBlock) );
2084 PpB->next = PpB->prev = NULL;
2086 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2087 PpB->tregisters = NULL;
2089 PpB->FlowTree = NULL;
2095 /*-----------------------------------------------------------------*/
2096 /* newpCodeChain - create a new chain of pCodes */
2097 /*-----------------------------------------------------------------*
2099 * This function will create a new pBlock and the pointer to the
2100 * pCode that is passed in will be the first pCode in the block.
2101 *-----------------------------------------------------------------*/
2104 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2107 pBlock *pB = newpBlock();
2109 pB->pcHead = pB->pcTail = pc;
2116 /*-----------------------------------------------------------------*/
2117 /* newpCodeOpLabel - Create a new label given the key */
2118 /* Note, a negative key means that the label is part of wild card */
2119 /* (and hence a wild card label) used in the pCodePeep */
2120 /* optimizations). */
2121 /*-----------------------------------------------------------------*/
2123 pCodeOp *newpCodeOpLabel(char *name, int key)
2126 static int label_key=-1;
2130 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2131 pcop->type = PO_LABEL;
2136 sprintf(s=buffer,"_%05d_DS_",key);
2138 s = name, key = label_key--;
2140 PCOLAB(pcop)->offset = 0;
2142 pcop->name = Safe_strdup(s);
2144 ((pCodeOpLabel *)pcop)->key = key;
2146 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2150 /*-----------------------------------------------------------------*/
2151 /*-----------------------------------------------------------------*/
2152 pCodeOp *newpCodeOpLit(int lit)
2158 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2159 pcop->type = PO_LITERAL;
2163 sprintf(s,"0x%02x",lit);
2165 pcop->name = Safe_strdup(s);
2168 ((pCodeOpLit *)pcop)->lit = lit;
2173 /*-----------------------------------------------------------------*/
2174 /*-----------------------------------------------------------------*/
2175 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2179 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2180 pcop->type = PO_IMMEDIATE;
2183 pcop->name = Safe_strdup(name);
2186 r = dirregWithName(name);
2190 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2191 PCOI(pcop)->rIdx = r->rIdx;
2193 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2194 PCOI(pcop)->rIdx = -1;
2196 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2201 PCOI(pcop)->index = index;
2202 PCOI(pcop)->offset = offset;
2203 PCOI(pcop)->_const = code_space;
2204 PCOI(pcop)->_function = is_func;
2209 /*-----------------------------------------------------------------*/
2210 /*-----------------------------------------------------------------*/
2211 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2217 if(!pcwb || !subtype) {
2218 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2222 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2223 pcop->type = PO_WILD;
2224 sprintf(s,"%%%d",id);
2225 pcop->name = Safe_strdup(s);
2227 PCOW(pcop)->id = id;
2228 PCOW(pcop)->pcwb = pcwb;
2229 PCOW(pcop)->subtype = subtype;
2230 PCOW(pcop)->matched = NULL;
2234 /*-----------------------------------------------------------------*/
2235 /* Find a symbol with matching name */
2236 /*-----------------------------------------------------------------*/
2237 static symbol *symFindWithName(memmap * map, const char *name)
2241 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2242 if (sym->rname && (strcmp(sym->rname,name)==0))
2248 /*-----------------------------------------------------------------*/
2249 /*-----------------------------------------------------------------*/
2250 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2255 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2256 pcop->type = PO_GPR_BIT;
2258 PCORB(pcop)->bit = ibit;
2259 PCORB(pcop)->inBitSpace = inBitSpace;
2261 if (name) r = regFindWithName(name);
2263 // Register has not been allocated - check for symbol information
2265 sym = symFindWithName(bit, name);
2266 if (!sym) sym = symFindWithName(sfrbit, name);
2267 if (!sym) sym = symFindWithName(sfr, name);
2269 r = allocNewDirReg(sym->etype,name);
2275 PCOR(pcop)->rIdx = r->rIdx;
2277 pcop->name = Safe_strdup(name);
2278 PCOR(pcop)->r = NULL;
2279 PCOR(pcop)->rIdx = 0;
2284 /*-----------------------------------------------------------------*
2285 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2287 * If rIdx >=0 then a specific register from the set of registers
2288 * will be selected. If rIdx <0, then a new register will be searched
2290 *-----------------------------------------------------------------*/
2292 pCodeOp *newpCodeOpReg(int rIdx)
2296 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2301 PCOR(pcop)->rIdx = rIdx;
2302 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2304 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2307 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2311 pcop->type = PCOR(pcop)->r->pc_type;
2316 pCodeOp *newpCodeOpRegFromStr(char *name)
2320 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2321 PCOR(pcop)->r = allocRegByName(name, 1);
2322 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2323 pcop->type = PCOR(pcop)->r->pc_type;
2324 pcop->name = PCOR(pcop)->r->name;
2329 pCodeOp *newpCodeOpStr(char *name)
2333 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2334 pcop->type = PO_STR;
2335 pcop->name = Safe_strdup(name);
2337 PCOS(pcop)->isPublic = 0;
2343 /*-----------------------------------------------------------------*/
2344 /*-----------------------------------------------------------------*/
2346 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2353 pcop = newpCodeOpBit(name, -1,0);
2357 pcop = newpCodeOpLit(-1);
2361 pcop = newpCodeOpLabel(NULL,-1);
2365 pcop = newpCodeOpReg(-1);
2368 case PO_GPR_POINTER:
2369 case PO_GPR_REGISTER:
2371 pcop = newpCodeOpRegFromStr(name);
2373 pcop = newpCodeOpReg(-1);
2377 pcop = newpCodeOpStr(name);
2381 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2384 pcop->name = Safe_strdup(name);
2392 /*-----------------------------------------------------------------*/
2393 /*-----------------------------------------------------------------*/
2394 void pCodeConstString(char *name, char *value)
2398 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2403 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2407 sprintf(buffer,"; %s = %s",name,value);
2409 addpCode2pBlock(pb,newpCodeCharP(buffer));
2410 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2413 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2419 /*-----------------------------------------------------------------*/
2420 /*-----------------------------------------------------------------*/
2421 void pCodeReadCodeTable(void)
2425 fprintf(stderr, " %s\n",__FUNCTION__);
2427 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2431 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2432 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2433 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2434 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2436 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2437 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2438 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2439 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2444 /*-----------------------------------------------------------------*/
2445 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2446 /*-----------------------------------------------------------------*/
2447 void addpCode2pBlock(pBlock *pb, pCode *pc)
2454 /* If this is the first pcode to be added to a block that
2455 * was initialized with a NULL pcode, then go ahead and
2456 * make this pcode the head and tail */
2457 pb->pcHead = pb->pcTail = pc;
2460 pb->pcTail->next = pc;
2462 pc->prev = pb->pcTail;
2469 /*-----------------------------------------------------------------*/
2470 /* addpBlock - place a pBlock into the pFile */
2471 /*-----------------------------------------------------------------*/
2472 void addpBlock(pBlock *pb)
2474 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2477 /* First time called, we'll pass through here. */
2478 //_ALLOC(the_pFile,sizeof(pFile));
2479 the_pFile = Safe_calloc(1,sizeof(pFile));
2480 the_pFile->pbHead = the_pFile->pbTail = pb;
2481 the_pFile->functions = NULL;
2485 the_pFile->pbTail->next = pb;
2486 pb->prev = the_pFile->pbTail;
2488 the_pFile->pbTail = pb;
2491 /*-----------------------------------------------------------------*/
2492 /* removepBlock - remove a pBlock from the pFile */
2493 /*-----------------------------------------------------------------*/
2494 void removepBlock(pBlock *pb)
2502 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2504 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2507 if(pbs == the_pFile->pbHead)
2508 the_pFile->pbHead = pbs->next;
2510 if (pbs == the_pFile->pbTail)
2511 the_pFile->pbTail = pbs->prev;
2514 pbs->next->prev = pbs->prev;
2517 pbs->prev->next = pbs->next;
2524 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2528 /*-----------------------------------------------------------------*/
2529 /* printpCode - write the contents of a pCode to a file */
2530 /*-----------------------------------------------------------------*/
2531 void printpCode(FILE *of, pCode *pc)
2542 fprintf(of,"warning - unable to print pCode\n");
2545 /*-----------------------------------------------------------------*/
2546 /* printpBlock - write the contents of a pBlock to a file */
2547 /*-----------------------------------------------------------------*/
2548 void printpBlock(FILE *of, pBlock *pb)
2558 for(pc = pb->pcHead; pc; pc = pc->next)
2563 /*-----------------------------------------------------------------*/
2565 /* pCode processing */
2569 /*-----------------------------------------------------------------*/
2571 void unlinkpCode(pCode *pc)
2577 fprintf(stderr,"Unlinking: ");
2578 printpCode(stderr, pc);
2581 pc->prev->next = pc->next;
2583 pc->next->prev = pc->prev;
2585 pc->prev = pc->next = NULL;
2589 /*-----------------------------------------------------------------*/
2590 /*-----------------------------------------------------------------*/
2592 static void genericDestruct(pCode *pc)
2598 /* For instructions, tell the register (if there's one used)
2599 * that it's no longer needed */
2600 regs *reg = getRegFromInstruction(pc);
2602 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2605 /* Instead of deleting the memory used by this pCode, mark
2606 * the object as bad so that if there's a pointer to this pCode
2607 * dangling around somewhere then (hopefully) when the type is
2608 * checked we'll catch it.
2613 addpCode2pBlock(pb_dead_pcodes, pc);
2620 /*-----------------------------------------------------------------*/
2621 /* Copies the pCodeInstruction flow pointer from source pCode */
2622 /*-----------------------------------------------------------------*/
2623 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2625 pCodeFlow *pcflow = 0;
2626 for (p=pcs; p; p=p->prev) {
2628 pcflow = PCI(p)->pcflow;
2632 pcflow = (pCodeFlow*)p;
2636 PCI(pcd)->pcflow = pcflow;
2639 /*-----------------------------------------------------------------*/
2640 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2641 /* into the pCode chain containing pc1 */
2642 /*-----------------------------------------------------------------*/
2643 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2649 pc2->next = pc1->next;
2651 pc1->next->prev = pc2;
2657 /* If this is an instrution type propogate the flow */
2659 CopyFlow(PCI(pc2),pc1);
2662 /*------------------------------------------------------------------*/
2663 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2664 /* into the pCode chain containing pc1 */
2665 /*------------------------------------------------------------------*/
2666 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2672 pc2->prev = pc1->prev;
2674 pc1->prev->next = pc2;
2680 /* If this is an instrution type propogate the flow */
2682 CopyFlow(PCI(pc2),pc1);
2685 /*-----------------------------------------------------------------*/
2686 /* pCodeOpCopy - copy a pcode operator */
2687 /*-----------------------------------------------------------------*/
2688 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2690 pCodeOp *pcopnew=NULL;
2695 switch(pcop->type) {
2698 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2699 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2700 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2701 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2706 /* Here we expand the wild card into the appropriate type: */
2707 /* By recursively calling pCodeOpCopy */
2708 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2709 if(PCOW(pcop)->matched)
2710 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2713 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2714 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2715 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2722 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2723 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2724 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2728 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2729 PCOI(pcopnew)->index = PCOI(pcop)->index;
2730 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2731 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2732 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2736 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2737 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2738 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2743 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2744 PCOR(pcopnew)->r = PCOR(pcop)->r;
2745 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2746 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2750 case PO_GPR_POINTER:
2751 case PO_GPR_REGISTER:
2755 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2756 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2757 PCOR(pcopnew)->r = PCOR(pcop)->r;
2758 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2759 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2760 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2764 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2765 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2766 PCOR(pcopnew)->r = PCOR(pcop)->r;
2767 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2768 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2771 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2772 case PO_SFR_REGISTER:
2780 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2781 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2785 pcopnew->type = pcop->type;
2787 pcopnew->name = Safe_strdup(pcop->name);
2789 pcopnew->name = NULL;
2794 /*-----------------------------------------------------------------*/
2795 /* popCopyReg - copy a pcode operator */
2796 /*-----------------------------------------------------------------*/
2797 pCodeOp *popCopyReg(pCodeOpReg *pc)
2801 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2802 pcor->pcop.type = pc->pcop.type;
2804 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2805 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2807 pcor->pcop.name = NULL;
2810 pcor->rIdx = pc->rIdx;
2813 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2818 /*-----------------------------------------------------------------*/
2819 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2820 /*-----------------------------------------------------------------*/
2821 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2823 pCodeInstruction *new_pci;
2826 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2828 new_pci = PCI(newpCode(pci->op,pci->pcop));
2830 new_pci->pc.pb = pci->pc.pb;
2831 new_pci->from = pci->from;
2832 new_pci->to = pci->to;
2833 new_pci->label = pci->label;
2834 new_pci->pcflow = pci->pcflow;
2836 return PCODE(new_pci);
2839 /*-----------------------------------------------------------------*/
2840 /*-----------------------------------------------------------------*/
2841 void pCodeDeleteChain(pCode *f,pCode *t)
2846 DFPRINTF((stderr,"delete pCode:\n"));
2848 //f->print(stderr,f);
2849 //f->delete(f); this dumps core...
2854 /*-----------------------------------------------------------------*/
2855 /*-----------------------------------------------------------------*/
2856 void pBlockRegs(FILE *of, pBlock *pb)
2861 r = setFirstItem(pb->tregisters);
2863 r = setNextItem(pb->tregisters);
2868 /*-----------------------------------------------------------------*/
2869 /*-----------------------------------------------------------------*/
2870 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2875 int use_buffer = 1; // copy the string to the passed buffer pointer
2880 use_buffer = 0; // Don't bother copying the string to the buffer.
2884 switch(pcop->type) {
2888 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2891 //return PCOR(pcop)->r->name;
2895 if (PCOR(pcop)->r->type == REG_STK)
2896 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2898 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2901 SAFE_snprintf(&buffer,&size,"%s",r->name);
2911 if(PCOI(pcop)->_const) {
2913 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2914 switch(PCOI(pcop)->offset) {
2916 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2919 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2922 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2925 8 * PCOI(pcop)->offset );
2928 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2931 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2932 SAFE_snprintf(&s,&size,"(%s + %d)",
2934 PCOI(pcop)->index );
2936 switch(PCOI(pcop)->offset) {
2938 SAFE_snprintf(&s,&size,"%s",pcop->name);
2941 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2944 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2953 //size = sizeof(buffer);
2954 if( PCOR(pcop)->instance) {
2955 SAFE_snprintf(&s,&size,"(%s + %d)",
2957 PCOR(pcop)->instance );
2958 //fprintf(stderr,"PO_DIR %s\n",buffer);
2960 SAFE_snprintf(&s,&size,"%s",pcop->name);
2966 if(PCOLAB(pcop)->offset == 1)
2967 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2969 SAFE_snprintf(&s,&size,"%s",pcop->name);
2976 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2979 return PCOR(pcop)->r->name;
2982 /* fall through to the default case */
2986 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2994 printf("PIC port internal warning: (%s:%d) %s not found\n",
2999 return "NO operand";
3003 /*-----------------------------------------------------------------*/
3004 /*-----------------------------------------------------------------*/
3005 static char *get_op_from_instruction( pCodeInstruction *pcc)
3009 return get_op(pcc->pcop,NULL,0);
3011 return ("ERROR Null: get_op_from_instruction");
3015 /*-----------------------------------------------------------------*/
3016 /*-----------------------------------------------------------------*/
3017 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3019 fprintf(of,"pcodeopprint- not implemented\n");
3022 /*-----------------------------------------------------------------*/
3023 /*-----------------------------------------------------------------*/
3024 char *pCode2str(char *str, size_t size, pCode *pc)
3032 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3034 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3036 if(PCI(pc)->isBitInst) {
3037 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3038 char *name = PCI(pc)->pcop->name;
3040 name = PCOR(PCI(pc)->pcop)->r->name;
3041 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3042 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3044 SAFE_snprintf(&s,&size,"%s,%d", name,
3045 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3046 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3047 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3049 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3050 //PCI(pc)->pcop->t.bit );
3053 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3054 if( PCI(pc)->num_ops == 2)
3055 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3057 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3060 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3062 if( PCI(pc)->num_ops == 2)
3063 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3071 /* assuming that comment ends with a \n */
3072 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3076 /* assuming that inline code ends with a \n */
3077 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3081 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3084 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3087 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3090 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3093 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3097 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3104 /*-----------------------------------------------------------------*/
3105 /* genericPrint - the contents of a pCode to a file */
3106 /*-----------------------------------------------------------------*/
3107 static void genericPrint(FILE *of, pCode *pc)
3115 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3119 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3123 // If the opcode has a label, print that first
3126 pCodeInstruction *pci = PCI(pc);
3127 pBranch *pbl = pci->label;
3128 while(pbl && pbl->pc) {
3129 if(pbl->pc->type == PC_LABEL)
3130 pCodePrintLabel(of, pbl->pc);
3135 genericPrint(of,PCODE(pci->cline));
3138 pCode2str(str, 256, pc);
3140 fprintf(of,"%s",str);
3144 pCodeOpReg *pcor = PCOR(pci->pcop);
3145 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3147 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3148 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3149 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3154 pBranch *dpb = pc->to; // debug
3156 switch ( dpb->pc->type) {
3158 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3161 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3164 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3167 fprintf(of, "\t;flow");
3181 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3182 if(PCW(pc)->pci.label)
3183 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3185 if(PCW(pc)->operand) {
3186 fprintf(of,";\toperand ");
3187 pCodeOpPrint(of,PCW(pc)->operand );
3193 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3194 if(PCFL(pc)->ancestor)
3195 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3202 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3206 fprintf(of,"unknown pCode type %d\n",pc->type);
3211 /*-----------------------------------------------------------------*/
3212 /* pCodePrintFunction - prints function begin/end */
3213 /*-----------------------------------------------------------------*/
3215 static void pCodePrintFunction(FILE *of, pCode *pc)
3221 if( ((pCodeFunction *)pc)->modname)
3222 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3224 if(PCF(pc)->fname) {
3225 pBranch *exits = PCF(pc)->to;
3227 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3230 exits = exits->next;
3233 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3236 if((PCF(pc)->from &&
3237 PCF(pc)->from->pc->type == PC_FUNCTION &&
3238 PCF(PCF(pc)->from->pc)->fname) )
3239 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3241 fprintf(of,"; exit point [can't find entry point]\n");
3244 /*-----------------------------------------------------------------*/
3245 /* pCodePrintLabel - prints label */
3246 /*-----------------------------------------------------------------*/
3248 static void pCodePrintLabel(FILE *of, pCode *pc)
3255 fprintf(of,"%s\n",PCL(pc)->label);
3256 else if (PCL(pc)->key >=0)
3257 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3259 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3262 /*-----------------------------------------------------------------*/
3263 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3264 /* remove it if it is found. */
3265 /*-----------------------------------------------------------------*/
3266 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3273 if(pcl->type == PC_OPCODE)
3274 b = PCI(pcl)->label;
3276 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3281 //fprintf (stderr, "%s \n",__FUNCTION__);
3282 //pcl->print(stderr,pcl);
3283 //pc->print(stderr,pc);
3286 //fprintf (stderr, "found label\n");
3290 bprev->next = b->next; /* Not first pCode in chain */
3294 PCI(pcl)->label = b->next; /* First pCode in chain */
3297 return; /* A label can't occur more than once */
3305 /*-----------------------------------------------------------------*/
3306 /*-----------------------------------------------------------------*/
3307 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3326 /*-----------------------------------------------------------------*/
3327 /* pBranchLink - given two pcodes, this function will link them */
3328 /* together through their pBranches */
3329 /*-----------------------------------------------------------------*/
3330 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3334 // Declare a new branch object for the 'from' pCode.
3336 //_ALLOC(b,sizeof(pBranch));
3337 b = Safe_calloc(1,sizeof(pBranch));
3338 b->pc = PCODE(t); // The link to the 'to' pCode.
3341 f->to = pBranchAppend(f->to,b);
3343 // Now do the same for the 'to' pCode.
3345 //_ALLOC(b,sizeof(pBranch));
3346 b = Safe_calloc(1,sizeof(pBranch));
3350 t->from = pBranchAppend(t->from,b);
3355 /*-----------------------------------------------------------------*/
3356 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3358 /*-----------------------------------------------------------------*/
3359 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3372 /*-----------------------------------------------------------------*/
3373 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3374 /*-----------------------------------------------------------------*/
3375 static void pCodeUnlink(pCode *pc)
3380 if(!pc->prev || !pc->next) {
3381 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3385 /* first remove the pCode from the chain */
3386 pc->prev->next = pc->next;
3387 pc->next->prev = pc->prev;
3389 /* Now for the hard part... */
3391 /* Remove the branches */
3395 pc1 = pb1->pc; /* Get the pCode that branches to the
3396 * one we're unlinking */
3398 /* search for the link back to this pCode (the one we're
3400 if(pb2 = pBranchFind(pc1->to,pc)) {
3401 pb2->pc = pc->to->pc; // make the replacement
3403 /* if the pCode we're unlinking contains multiple 'to'
3404 * branches (e.g. this a skip instruction) then we need
3405 * to copy these extra branches to the chain. */
3407 pBranchAppend(pb2, pc->to->next);
3416 /*-----------------------------------------------------------------*/
3417 /*-----------------------------------------------------------------*/
3419 static void genericAnalyze(pCode *pc)
3429 // Go through the pCodes that are in pCode chain and link
3430 // them together through the pBranches. Note, the pCodes
3431 // are linked together as a contiguous stream like the
3432 // assembly source code lines. The linking here mimics this
3433 // except that comments are not linked in.
3435 pCode *npc = pc->next;
3437 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3438 pBranchLink(pc,npc);
3443 /* reached the end of the pcode chain without finding
3444 * an instruction we could link to. */
3448 fprintf(stderr,"analyze PC_FLOW\n");
3452 fprintf(stderr,";A bad pCode is being used\n");
3458 /*-----------------------------------------------------------------*/
3459 /*-----------------------------------------------------------------*/
3460 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3464 if(pc->type == PC_LABEL) {
3465 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3468 if(pc->type == PC_OPCODE) {
3469 pbr = PCI(pc)->label;
3471 if(pbr->pc->type == PC_LABEL) {
3472 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3482 /*-----------------------------------------------------------------*/
3483 /*-----------------------------------------------------------------*/
3484 int checkLabel(pCode *pc)
3488 if(pc && isPCI(pc)) {
3489 pbr = PCI(pc)->label;
3491 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3501 /*-----------------------------------------------------------------*/
3502 /* findLabelinpBlock - Search the pCode for a particular label */
3503 /*-----------------------------------------------------------------*/
3504 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3511 for(pc = pb->pcHead; pc; pc = pc->next)
3512 if(compareLabel(pc,pcop_label))
3518 /*-----------------------------------------------------------------*/
3519 /* findLabel - Search the pCode for a particular label */
3520 /*-----------------------------------------------------------------*/
3521 pCode * findLabel(pCodeOpLabel *pcop_label)
3529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3530 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3534 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3538 /*-----------------------------------------------------------------*/
3539 /* findNextpCode - given a pCode, find the next of type 'pct' */
3540 /* in the linked list */
3541 /*-----------------------------------------------------------------*/
3542 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3555 /*-----------------------------------------------------------------*/
3556 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3557 /* in the linked list */
3558 /*-----------------------------------------------------------------*/
3559 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3563 if(pc->type == pct) {
3565 static unsigned int stop;
3567 stop++; // Place break point here
3578 /*-----------------------------------------------------------------*/
3579 /* findNextInstruction - given a pCode, find the next instruction */
3580 /* in the linked list */
3581 /*-----------------------------------------------------------------*/
3582 pCode * findNextInstruction(pCode *pci)
3587 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD)) {
3589 static unsigned int stop;
3591 stop++; // Place break point here
3597 fprintf(stderr,"findNextInstruction: ");
3598 printpCode(stderr, pc);
3603 //fprintf(stderr,"Couldn't find instruction\n");
3607 /*-----------------------------------------------------------------*/
3608 /* findNextInstruction - given a pCode, find the next instruction */
3609 /* in the linked list */
3610 /*-----------------------------------------------------------------*/
3611 pCode * findPrevInstruction(pCode *pci)
3613 return findPrevpCode(pci, PC_OPCODE);
3616 /*-----------------------------------------------------------------*/
3617 /* findFunctionEnd - given a pCode find the end of the function */
3618 /* that contains it */
3619 /*-----------------------------------------------------------------*/
3620 pCode * findFunctionEnd(pCode *pc)
3624 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3630 fprintf(stderr,"Couldn't find function end\n");
3635 /*-----------------------------------------------------------------*/
3636 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3637 /* instruction with which it is associated. */
3638 /*-----------------------------------------------------------------*/
3639 static void AnalyzeLabel(pCode *pc)
3648 static void AnalyzeGOTO(pCode *pc)
3651 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3655 static void AnalyzeSKIP(pCode *pc)
3658 pBranchLink(pc,findNextInstruction(pc->next));
3659 pBranchLink(pc,findNextInstruction(pc->next->next));
3663 static void AnalyzeRETURN(pCode *pc)
3666 // branch_link(pc,findFunctionEnd(pc->next));
3672 /*-----------------------------------------------------------------*/
3673 /*-----------------------------------------------------------------*/
3674 regs * getRegFromInstruction(pCode *pc)
3680 PCI(pc)->num_ops == 0 )
3683 switch(PCI(pc)->pcop->type) {
3686 return PCOR(PCI(pc)->pcop)->r;
3688 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3692 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3693 return PCOR(PCI(pc)->pcop)->r;
3696 if(PCOI(PCI(pc)->pcop)->r)
3697 return (PCOI(PCI(pc)->pcop)->r);
3699 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3700 return dirregWithName(PCI(pc)->pcop->name);
3701 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3704 return PCOR(PCI(pc)->pcop)->r;
3706 case PO_GPR_REGISTER:
3708 //fprintf(stderr, "getRegFromInstruction - dir\n");
3709 return PCOR(PCI(pc)->pcop)->r;
3711 //fprintf(stderr, "getRegFromInstruction - literal\n");
3715 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3716 //genericPrint(stderr, pc);
3724 /*-----------------------------------------------------------------*/
3725 /*-----------------------------------------------------------------*/
3727 void AnalyzepBlock(pBlock *pb)
3734 /* Find all of the registers used in this pBlock
3735 * by looking at each instruction and examining it's
3738 for(pc = pb->pcHead; pc; pc = pc->next) {
3740 /* Is this an instruction with operands? */
3741 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3743 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3744 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3746 /* Loop through all of the registers declared so far in
3747 this block and see if we find this one there */
3749 regs *r = setFirstItem(pb->tregisters);
3752 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3753 PCOR(PCI(pc)->pcop)->r = r;
3756 r = setNextItem(pb->tregisters);
3760 /* register wasn't found */
3761 //r = Safe_calloc(1, sizeof(regs));
3762 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3763 //addSet(&pb->tregisters, r);
3764 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3765 //PCOR(PCI(pc)->pcop)->r = r;
3766 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3768 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3771 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3772 if(PCOR(PCI(pc)->pcop)->r) {
3773 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3774 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3776 if(PCI(pc)->pcop->name)
3777 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3779 fprintf(stderr,"ERROR: NULL register\n");
3788 /*-----------------------------------------------------------------*/
3790 /*-----------------------------------------------------------------*/
3791 void InsertpFlow(pCode *pc, pCode **pflow)
3794 PCFL(*pflow)->end = pc;
3796 if(!pc || !pc->next)
3799 *pflow = newpCodeFlow();
3800 pCodeInsertAfter(pc, *pflow);
3803 /*-----------------------------------------------------------------*/
3804 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3805 /* the flow blocks. */
3807 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3808 * point the instruction flow changes.
3810 /*-----------------------------------------------------------------*/
3811 void BuildFlow(pBlock *pb)
3814 pCode *last_pci=NULL;
3821 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3822 /* Insert a pCodeFlow object at the beginning of a pBlock */
3824 InsertpFlow(pb->pcHead, &pflow);
3826 //pflow = newpCodeFlow(); /* Create a new Flow object */
3827 //pflow->next = pb->pcHead; /* Make the current head the next object */
3828 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3829 //pb->pcHead = pflow; /* Make the Flow object the head */
3832 for( pc = findNextInstruction(pb->pcHead);
3834 pc=findNextInstruction(pc)) {
3837 PCI(pc)->pcflow = PCFL(pflow);
3839 //fprintf(stderr," build: ");
3840 //pflow->print(stderr,pflow);
3842 if( PCI(pc)->isSkip) {
3844 /* The two instructions immediately following this one
3845 * mark the beginning of a new flow segment */
3847 while(pc && PCI(pc)->isSkip) {
3849 PCI(pc)->pcflow = PCFL(pflow);
3853 InsertpFlow(pc, &pflow);
3854 pc=findNextInstruction(pc->next);
3862 PCI(pc)->pcflow = PCFL(pflow);
3864 InsertpFlow(pc, &pflow);
3866 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3868 InsertpFlow(pc, &pflow);
3871 } else if (checkLabel(pc)) {
3873 /* This instruction marks the beginning of a
3874 * new flow segment */
3879 /* If the previous pCode is not a flow object, then
3880 * insert a new flow object. (This check prevents
3881 * two consecutive flow objects from being insert in
3882 * the case where a skip instruction preceeds an
3883 * instruction containing a label.) */
3885 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3886 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3888 PCI(pc)->pcflow = PCFL(pflow);
3895 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3897 PCFL(pflow)->end = pb->pcTail;
3900 /*-------------------------------------------------------------------*/
3901 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3902 /* the flow blocks. */
3904 * unBuildFlow removes pCodeFlow objects from a pCode chain
3906 /*-----------------------------------------------------------------*/
3907 void unBuildFlow(pBlock *pb)
3922 if(PCI(pc)->pcflow) {
3923 //free(PCI(pc)->pcflow);
3924 PCI(pc)->pcflow = NULL;
3927 } else if(isPCFL(pc) )
3936 /*-----------------------------------------------------------------*/
3937 /*-----------------------------------------------------------------*/
3938 void dumpCond(int cond)
3941 static char *pcc_str[] = {
3955 int ncond = sizeof(pcc_str) / sizeof(char *);
3958 fprintf(stderr, "0x%04X\n",cond);
3960 for(i=0,j=1; i<ncond; i++, j<<=1)
3962 fprintf(stderr, " %s\n",pcc_str[i]);
3966 /*-----------------------------------------------------------------*/
3967 /*-----------------------------------------------------------------*/
3968 void FlowStats(pCodeFlow *pcflow)
3976 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3978 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3981 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3986 fprintf(stderr, " FlowStats inCond: ");
3987 dumpCond(pcflow->inCond);
3988 fprintf(stderr, " FlowStats outCond: ");
3989 dumpCond(pcflow->outCond);
3993 /*-----------------------------------------------------------------*
3994 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3995 * if it affects the banking bits.
3997 * return: -1 == Banking bits are unaffected by this pCode.
3999 * return: > 0 == Banking bits are affected.
4001 * If the banking bits are affected, then the returned value describes
4002 * which bits are affected and how they're affected. The lower half
4003 * of the integer maps to the bits that are affected, the upper half
4004 * to whether they're set or cleared.
4006 *-----------------------------------------------------------------*/
4008 #define SET_BANK_BIT (1 << 16)
4009 #define CLR_BANK_BIT 0
4011 static int isBankInstruction(pCode *pc)
4019 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4021 // Check to see if the register banks are changing
4022 if(PCI(pc)->isModReg) {
4024 pCodeOp *pcop = PCI(pc)->pcop;
4025 switch(PCI(pc)->op) {
4028 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4029 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4030 return SET_BANK_BIT | PIC_RP0_BIT;
4033 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4034 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4035 return CLR_BANK_BIT | PIC_RP0_BIT;
4040 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4041 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4042 return CLR_BANK_BIT | PIC_RP1_BIT;
4044 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4045 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4046 return CLR_BANK_BIT | PIC_RP1_BIT;
4050 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4051 //genericPrint(stderr, pc);
4062 /*-----------------------------------------------------------------*/
4063 /*-----------------------------------------------------------------*/
4065 static void FillFlow(pCodeFlow *pcflow)
4073 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4075 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4078 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4085 isBankInstruction(pc);
4087 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4090 fprintf(stderr, " FillFlow - Bad end of flow\n");
4092 fprintf(stderr, " FillFlow - Ending flow with\n ");
4093 pc->print(stderr,pc);
4096 fprintf(stderr, " FillFlow inCond: ");
4097 dumpCond(pcflow->inCond);
4098 fprintf(stderr, " FillFlow outCond: ");
4099 dumpCond(pcflow->outCond);
4104 /*-----------------------------------------------------------------*/
4105 /*-----------------------------------------------------------------*/
4106 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4108 pCodeFlowLink *fromLink, *toLink;
4110 if(!from || !to || !to->pcflow || !from->pcflow)
4113 fromLink = newpCodeFlowLink(from->pcflow);
4114 toLink = newpCodeFlowLink(to->pcflow);
4116 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4117 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4121 /*-----------------------------------------------------------------*
4122 * void LinkFlow(pBlock *pb)
4124 * In BuildFlow, the PIC code has been partitioned into contiguous
4125 * non-branching segments. In LinkFlow, we determine the execution
4126 * order of these segments. For example, if one of the segments ends
4127 * with a skip, then we know that there are two possible flow segments
4128 * to which control may be passed.
4129 *-----------------------------------------------------------------*/
4130 void LinkFlow(pBlock *pb)
4136 //fprintf(stderr,"linkflow \n");
4138 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4140 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4143 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4145 //fprintf(stderr," link: ");
4146 //pcflow->print(stderr,pcflow);
4148 //FillFlow(PCFL(pcflow));
4150 pc = PCFL(pcflow)->end;
4152 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4153 if(isPCI_SKIP(pc)) {
4154 //fprintf(stderr, "ends with skip\n");
4155 //pc->print(stderr,pc);
4156 pct=findNextInstruction(pc->next);
4157 LinkFlow_pCode(PCI(pc),PCI(pct));
4158 pct=findNextInstruction(pct->next);
4159 LinkFlow_pCode(PCI(pc),PCI(pct));
4163 if(isPCI_BRANCH(pc)) {
4164 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4166 //fprintf(stderr, "ends with branch\n ");
4167 //pc->print(stderr,pc);
4169 if(!(pcol && isPCOLAB(pcol))) {
4170 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4171 pc->print(stderr,pc);
4172 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4177 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4178 LinkFlow_pCode(PCI(pc),PCI(pct));
4180 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4181 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4182 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4188 //fprintf(stderr, "ends with non-branching instruction:\n");
4189 //pc->print(stderr,pc);
4191 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4197 //fprintf(stderr, "ends with unknown\n");
4198 //pc->print(stderr,pc);
4202 //fprintf(stderr, "ends with nothing: ERROR\n");
4206 /*-----------------------------------------------------------------*/
4207 /*-----------------------------------------------------------------*/
4209 /*-----------------------------------------------------------------*/
4210 /*-----------------------------------------------------------------*/
4211 int isPCinFlow(pCode *pc, pCode *pcflow)
4217 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4220 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4226 /*-----------------------------------------------------------------*/
4227 /*-----------------------------------------------------------------*/
4229 static void BanksUsedFlow2(pCode *pcflow)
4238 if(!isPCFL(pcflow)) {
4239 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4243 pc = findNextInstruction(pcflow->next);
4245 PCFL(pcflow)->lastBank = -1;
4247 while(isPCinFlow(pc,pcflow)) {
4249 int bank_selected = isBankInstruction(pc);
4251 //if(PCI(pc)->pcflow)
4252 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4254 if(bank_selected > 0) {
4255 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4257 // This instruction is modifying banking bits before accessing registers
4259 PCFL(pcflow)->firstBank = -1;
4261 if(PCFL(pcflow)->lastBank == -1)
4262 PCFL(pcflow)->lastBank = 0;
4264 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4265 if(bank_selected & SET_BANK_BIT)
4266 PCFL(pcflow)->lastBank |= bank;
4270 reg = getRegFromInstruction(pc);
4272 if(reg && !isREGinBank(reg, bank)) {
4273 int allbanks = REGallBanks(reg);
4275 PCFL(pcflow)->firstBank = allbanks;
4277 PCFL(pcflow)->lastBank = allbanks;
4284 pc = findNextInstruction(pc->next);
4287 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4288 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4291 /*-----------------------------------------------------------------*/
4292 /*-----------------------------------------------------------------*/
4294 static void BanksUsedFlow(pBlock *pb)
4299 //pb->pcHead->print(stderr, pb->pcHead);
4301 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4302 //pcflow->print(stderr,pcflow);
4304 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4306 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4308 BanksUsedFlow2(pcflow);
4314 /*-----------------------------------------------------------------*/
4315 /*-----------------------------------------------------------------*/
4316 static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci)
4319 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4321 /* Move the label, if there is one */
4324 new_pci->label = pci->label;
4328 /* Move the C code comment, if there is one */
4331 new_pci->cline = pci->cline;
4335 /* The new instruction has the same pcflow block */
4336 new_pci->pcflow = pci->pcflow;
4340 /*-----------------------------------------------------------------*/
4341 /*-----------------------------------------------------------------*/
4342 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4346 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4348 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4351 /*-----------------------------------------------------------------*/
4352 /*-----------------------------------------------------------------*/
4353 static void insertBankSel(pCodeInstruction *pci, const char *name)
4357 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4358 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4359 if (pcop->name == 0)
4360 pcop->name = strdup(name);
4361 new_pc = newpCode(POC_BANKSEL, pcop);
4363 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4366 /*-----------------------------------------------------------------*/
4367 /* If the register is a fixed known addess then we can assign the */
4368 /* bank selection bits. Otherwise the linker is going to assign */
4369 /* the register location and thus has to set bank selection bits */
4370 /* through the banksel directive. */
4371 /* One critical assumption here is that within this C module all */
4372 /* the locally allocated registers are in the same udata sector. */
4373 /* Therefore banksel is only called for external registers or the */
4374 /* first time a local register is encountered. */
4375 /*-----------------------------------------------------------------*/
4376 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4377 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4380 int a = reg->alias>>7;
4382 return cur_bank; // This register is available in all banks
4383 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4384 return cur_bank; // This register is available in banks 0 & 1
4386 if (reg->address&0x80) {
4387 if ((cur_bank==1)||(cur_bank==3)) {
4388 return cur_bank; // This register is available in banks 1 & 3
4391 if ((cur_bank==0)||(cur_bank==1)) {
4392 return cur_bank; // This register is available in banks 0 & 2
4397 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4399 LastRegIdx = reg->rIdx;
4402 bank = REG_BANK(reg);
4403 } else if (reg->isExtern) {
4404 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4406 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4408 if ((cur_bank == 'L')&&(bank == 'L')) { // If current bank and new bank are both allocated locally by the linker, then assume it is in same bank.
4409 return 'L'; // Local registers are presumed to be in same linker assigned bank
4410 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4411 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4412 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4413 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4414 } else if ((cur_bank == -1)||(cur_bank == 'L')||(cur_bank == 'E')) { // Current bank unknown and new register bank is known then can set bank bits
4415 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4416 if (getMaxRam()&0x100)
4417 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4418 } else { // Current bank and new register banks known - can set bank bits
4419 switch((cur_bank^bank) & 3) {
4423 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4426 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4429 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4430 if (getMaxRam()&0x100)
4431 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4439 /*-----------------------------------------------------------------*/
4440 /* Check for bank selection pcodes instructions and modify */
4441 /* cur_bank to match. */
4442 /*-----------------------------------------------------------------*/
4443 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4445 if (isSTATUS_REG(reg)) {
4447 if (PCI(pc)->op == POC_BCF) {
4448 int old_bank = *cur_bank;
4449 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4450 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4451 if (*cur_bank & ~(0x3))
4454 *cur_bank = *cur_bank&0x2;
4455 LastRegIdx = reg->rIdx;
4456 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4457 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4458 if (*cur_bank & ~(0x3))
4461 *cur_bank = *cur_bank&0x1;
4462 LastRegIdx = reg->rIdx;
4464 return old_bank != *cur_bank;
4467 if (PCI(pc)->op == POC_BSF) {
4468 int old_bank = *cur_bank;
4469 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4470 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4471 if (*cur_bank & ~(0x3))
4474 *cur_bank = (*cur_bank&0x2) | 0x1;
4475 LastRegIdx = reg->rIdx;
4476 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4477 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4478 if (*cur_bank & ~(0x3))
4481 *cur_bank = (*cur_bank&0x1) | 0x2;
4482 LastRegIdx = reg->rIdx;
4484 return old_bank != *cur_bank;
4487 } else if (PCI(pc)->op == POC_BANKSEL) {
4488 int old_bank = *cur_bank;
4489 *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L';
4490 LastRegIdx = reg->rIdx;
4491 return old_bank != *cur_bank;
4497 /*-----------------------------------------------------------------*/
4498 /* Set bank selection if necessary */
4499 /*-----------------------------------------------------------------*/
4500 static int DoBankSelect(pCode *pc, int cur_bank) {
4508 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4509 if (pcf && isPCF(pcf)) {
4511 int rbank = 'U'; // Undetermined
4512 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4513 // Check all the returns to work out what bank is selected
4514 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4516 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4518 rbank = PCFL(pcfr)->lastBank;
4520 if (rbank != PCFL(pcfr)->lastBank)
4521 return -1; // Unknown bank - multiple returns with different banks
4526 return -1; // Unknown bank
4528 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4529 /* Extern functions may use registers in different bank - must call banksel */
4530 return -1; /* Unknown bank */
4534 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4535 return -1; /* New bank unknown - linkers choice. */
4538 reg = getRegFromInstruction(pc);
4541 if (IsBankChange(pc,reg,&cur_bank))
4544 if (!isPCI_LIT(pc)) {
4546 /* Examine the instruction before this one to make sure it is
4547 * not a skip type instruction */
4548 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4550 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4551 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4553 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4555 if (!PCI(pc)->pcflow)
4556 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4558 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4564 /*-----------------------------------------------------------------*/
4565 /*-----------------------------------------------------------------*/
4567 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4575 pc = findNextInstruction(pcfl->pc.next);
4577 while(isPCinFlow(pc,PCODE(pcfl))) {
4579 cur_bank = DoBankSelect(pc,cur_bank);
4581 pc = findNextInstruction(pc->next);
4585 if(pcprev && cur_bank) {
4586 // Set bank state to unknown at the end of each flow block
4592 /*-----------------------------------------------------------------*/
4593 /*int compareBankFlow - compare the banking requirements between */
4595 /*-----------------------------------------------------------------*/
4597 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4600 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4603 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4606 if(pcflow->firstBank == -1)
4610 if(pcflowLink->pcflow->firstBank == -1) {
4611 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4612 pcflowLink->pcflow->to :
4613 pcflowLink->pcflow->from);
4614 return compareBankFlow(pcflow, pctl, toORfrom);
4618 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4621 pcflowLink->bank_conflict++;
4622 pcflowLink->pcflow->FromConflicts++;
4623 pcflow->ToConflicts++;
4626 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4629 pcflowLink->bank_conflict++;
4630 pcflowLink->pcflow->ToConflicts++;
4631 pcflow->FromConflicts++;
4635 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4636 pcflowLink->pcflow->pc.seq,
4637 pcflowLink->pcflow->FromConflicts,
4638 pcflowLink->pcflow->ToConflicts);
4644 /*-----------------------------------------------------------------*/
4645 /*-----------------------------------------------------------------*/
4647 void FixBankFlow(pBlock *pb)
4651 pCodeFlowLink *pcfl;
4653 pCode *pcflow_max_To=NULL;
4654 pCode *pcflow_max_From=NULL;
4655 int max_ToConflicts=0;
4656 int max_FromConflicts=0;
4658 /fprintf(stderr,"Fix Bank flow \n");
4659 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4663 First loop through all of the flow objects in this pcode block
4664 and fix the ones that have banking conflicts between the
4668 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4670 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4672 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4674 if(!isPCFL(pcflow)) {
4675 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4679 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4680 PCFL(pcflow)->firstBank >= 0 &&
4681 PCFL(pcflow)->lastBank >= 0 ) {
4683 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4684 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4686 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4687 BanksUsedFlow2(pcflow);
4692 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4694 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4696 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4701 if(!isPCFL(pcflow)) {
4702 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4706 PCFL(pcflow)->FromConflicts = 0;
4707 PCFL(pcflow)->ToConflicts = 0;
4712 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4713 pcfl = setFirstItem(PCFL(pcflow)->from);
4716 pc = PCODE(pcfl->pcflow);
4719 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4720 pc->print(stderr,pc);
4723 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4726 pcfl=setNextItem(PCFL(pcflow)->from);
4729 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4730 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4732 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4733 BanksUsedFlow2(pcflow);
4735 continue; / * Don't need to check the flow from here - it's already been fixed * /
4742 pcfl = setFirstItem(PCFL(pcflow)->to);
4745 pc = PCODE(pcfl->pcflow);
4747 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4748 pc->print(stderr,pc);
4751 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4754 pcfl=setNextItem(PCFL(pcflow)->to);
4757 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4758 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4760 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4761 BanksUsedFlow2(pcflow);
4766 Loop through the flow objects again and find the ones with the
4770 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4772 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4774 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4775 pcflow_max_To = pcflow;
4777 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4778 pcflow_max_From = pcflow;
4782 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4783 PCFL(pcflow_max_To)->pc.seq,
4784 PCFL(pcflow_max_To)->ToConflicts);
4787 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4788 PCFL(pcflow_max_From)->pc.seq,
4789 PCFL(pcflow_max_From)->FromConflicts);
4794 /*-----------------------------------------------------------------*/
4795 /*-----------------------------------------------------------------*/
4796 void DumpFlow(pBlock *pb)
4800 pCodeFlowLink *pcfl;
4803 fprintf(stderr,"Dump flow \n");
4804 pb->pcHead->print(stderr, pb->pcHead);
4806 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4807 pcflow->print(stderr,pcflow);
4809 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4811 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4813 if(!isPCFL(pcflow)) {
4814 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4817 fprintf(stderr,"dumping: ");
4818 pcflow->print(stderr,pcflow);
4819 FlowStats(PCFL(pcflow));
4821 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4823 pc = PCODE(pcfl->pcflow);
4825 fprintf(stderr, " from seq %d:\n",pc->seq);
4827 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4828 pc->print(stderr,pc);
4833 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4835 pc = PCODE(pcfl->pcflow);
4837 fprintf(stderr, " to seq %d:\n",pc->seq);
4839 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4840 pc->print(stderr,pc);
4849 /*-----------------------------------------------------------------*/
4850 /*-----------------------------------------------------------------*/
4851 int OptimizepBlock(pBlock *pb)
4856 if(!pb || !peepOptimizing)
4859 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4861 for(pc = pb->pcHead; pc; pc = pc->next)
4862 matches += pCodePeepMatchRule(pc);
4865 pc = findNextInstruction(pb->pcHead);
4873 if(pCodePeepMatchRule(pc)) {
4878 pc = findNextInstruction(pcprev->next);
4880 pc = findNextInstruction(pb->pcHead);
4882 pc = findNextInstruction(pc->next);
4886 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4891 /*-----------------------------------------------------------------*/
4892 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4893 /*-----------------------------------------------------------------*/
4894 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4898 for(pc = pcs; pc; pc = pc->next) {
4900 if((pc->type == PC_OPCODE) &&
4902 (PCI(pc)->pcop->type == PO_LABEL) &&
4903 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4911 /*-----------------------------------------------------------------*/
4912 /*-----------------------------------------------------------------*/
4913 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4920 (PCI(pc)->pcop->type == PO_LABEL)) {
4922 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4924 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4926 free(pcol->pcop.name);
4928 /* If the key is negative, then we (probably) have a label to
4929 * a function and the name is already defined */
4932 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4936 //sprintf(buffer,"_%05d_DS_",pcl->key);
4938 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4940 pcol->pcop.name = Safe_strdup(s);
4941 pcol->key = pcl->key;
4942 //pc->print(stderr,pc);
4949 /*-----------------------------------------------------------------*/
4950 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4951 /* pCode chain if they're not used. */
4952 /*-----------------------------------------------------------------*/
4953 void pBlockRemoveUnusedLabels(pBlock *pb)
4955 pCode *pc; pCodeLabel *pcl;
4960 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4962 pBranch *pbr = PCI(pc)->label;
4963 if(pbr && pbr->next) {
4964 pCode *pcd = pb->pcHead;
4966 //fprintf(stderr, "multiple labels\n");
4967 //pc->print(stderr,pc);
4972 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4973 //fprintf(stderr,"Used by:\n");
4974 //pcd->print(stderr,pcd);
4976 exchangeLabels(PCL(pbr->pc),pcd);
4985 for(pc = pb->pcHead; pc; pc = pc->next) {
4987 if(isPCL(pc)) // Label pcode
4989 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4990 pcl = PCL(PCI(pc)->label->pc);
4993 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4995 /* This pCode is a label, so search the pBlock to see if anyone
4998 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4999 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5000 /* Couldn't find an instruction that refers to this label
5001 * So, unlink the pCode label from it's pCode chain
5002 * and destroy the label */
5003 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5005 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5006 if(pc->type == PC_LABEL) {
5008 pCodeLabelDestruct(pc);
5010 unlinkpCodeFromBranch(pc, PCODE(pcl));
5011 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5022 /*-----------------------------------------------------------------*/
5023 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5024 /* chain and put them into pBranches that are */
5025 /* associated with the appropriate pCode */
5027 /*-----------------------------------------------------------------*/
5028 void pBlockMergeLabels(pBlock *pb)
5031 pCode *pc, *pcnext=NULL;
5036 /* First, Try to remove any unused labels */
5037 //pBlockRemoveUnusedLabels(pb);
5039 /* Now loop through the pBlock and merge the labels with the opcodes */
5042 // for(pc = pb->pcHead; pc; pc = pc->next) {
5045 pCode *pcn = pc->next;
5047 if(pc->type == PC_LABEL) {
5049 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5050 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5051 if((pcnext = findNextInstruction(pc) )) {
5053 // Unlink the pCode label from it's pCode chain
5056 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5057 // And link it into the instruction's pBranch labels. (Note, since
5058 // it's possible to have multiple labels associated with one instruction
5059 // we must provide a means to accomodate the additional labels. Thus
5060 // the labels are placed into the singly-linked list "label" as
5061 // opposed to being a single member of the pCodeInstruction.)
5063 //_ALLOC(pbr,sizeof(pBranch));
5064 pbr = Safe_calloc(1,sizeof(pBranch));
5068 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5071 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5073 } else if(pc->type == PC_CSOURCE) {
5075 /* merge the source line symbolic info into the next instruction */
5076 if((pcnext = findNextInstruction(pc) )) {
5078 // Unlink the pCode label from it's pCode chain
5080 PCI(pcnext)->cline = PCCS(pc);
5081 //fprintf(stderr, "merging CSRC\n");
5082 //genericPrint(stderr,pcnext);
5088 pBlockRemoveUnusedLabels(pb);
5092 /*-----------------------------------------------------------------*/
5093 /*-----------------------------------------------------------------*/
5094 int OptimizepCode(char dbName)
5096 #define MAX_PASSES 4
5105 DFPRINTF((stderr," Optimizing pCode\n"));
5109 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5110 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5111 matches += OptimizepBlock(pb);
5114 while(matches && ++passes < MAX_PASSES);
5119 /*-----------------------------------------------------------------*/
5120 /* popCopyGPR2Bit - copy a pcode operator */
5121 /*-----------------------------------------------------------------*/
5123 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5127 pcop = newpCodeOpBit(pc->name, bitval, 0);
5129 if( !( (pcop->type == PO_LABEL) ||
5130 (pcop->type == PO_LITERAL) ||
5131 (pcop->type == PO_STR) ))
5132 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5138 /*-----------------------------------------------------------------*/
5139 /*-----------------------------------------------------------------*/
5140 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5143 int firstBank = 'U';
5148 for (pc=pb->pcHead; pc; pc=pc->next) {
5150 firstBank = PCFL(pc)->firstBank;
5154 if (firstBank != 'U') {
5155 /* This block has already been done */
5156 if (firstBank != cur_bank) {
5157 /* This block has started with a different bank - must adjust it */
5158 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5161 regs *reg = getRegFromInstruction(pc);
5163 DoBankSelect(pc,cur_bank);
5173 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5176 for (pc=pb->pcHead; pc; pc=pc->next) {
5178 PCFL(pc)->firstBank = cur_bank;
5181 cur_bank = DoBankSelect(pc,cur_bank);
5184 /* Trace through branches and set the bank selection as required. */
5187 for (pc=pb->pcHead; pc; pc=pc->next) {
5189 PCFL(pc)->firstBank = cur_bank;
5193 if (PCI(pc)->op == POC_GOTO) {
5194 int lastRegIdx = LastRegIdx;
5196 /* Trace through branch */
5197 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5200 regs *reg = getRegFromInstruction(pcl);
5202 int bankUnknown = -1;
5203 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5205 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5211 LastRegIdx = lastRegIdx;
5213 /* Keep track out current bank */
5214 regs *reg = getRegFromInstruction(pc);
5216 IsBankChange(pc,reg,&cur_bank);
5223 /*-----------------------------------------------------------------*/
5224 /*-----------------------------------------------------------------*/
5225 void pBlockDestruct(pBlock *pb)
5236 /*-----------------------------------------------------------------*/
5237 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5238 /* name dbName and combine them */
5239 /* into one block */
5240 /*-----------------------------------------------------------------*/
5241 void mergepBlocks(char dbName)
5244 pBlock *pb, *pbmerged = NULL,*pbn;
5246 pb = the_pFile->pbHead;
5248 //fprintf(stderr," merging blocks named %c\n",dbName);
5252 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5253 if( getpBlock_dbName(pb) == dbName) {
5255 //fprintf(stderr," merged block %c\n",dbName);
5260 addpCode2pBlock(pbmerged, pb->pcHead);
5261 /* addpCode2pBlock doesn't handle the tail: */
5262 pbmerged->pcTail = pb->pcTail;
5264 pb->prev->next = pbn;
5266 pbn->prev = pb->prev;
5271 //printpBlock(stderr, pbmerged);
5278 /*-----------------------------------------------------------------*/
5279 /* AnalyzeFlow - Examine the flow of the code and optimize */
5281 /* level 0 == minimal optimization */
5282 /* optimize registers that are used only by two instructions */
5283 /* level 1 == maximal optimization */
5284 /* optimize by looking at pairs of instructions that use the */
5286 /*-----------------------------------------------------------------*/
5288 void AnalyzeFlow(int level)
5290 static int times_called=0;
5298 /* if this is not the first time this function has been called,
5299 then clean up old flow information */
5300 if(times_called++) {
5301 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5304 RegsUnMapLiveRanges();
5310 /* Phase 2 - Flow Analysis - Register Banking
5312 * In this phase, the individual flow blocks are examined
5313 * and register banking is fixed.
5316 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5317 //FixRegisterBanking(pb);
5319 /* Phase 2 - Flow Analysis
5321 * In this phase, the pCode is partition into pCodeFlow
5322 * blocks. The flow blocks mark the points where a continuous
5323 * stream of instructions changes flow (e.g. because of
5324 * a call or goto or whatever).
5327 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5331 /* Phase 2 - Flow Analysis - linking flow blocks
5333 * In this phase, the individual flow blocks are examined
5334 * to determine their order of excution.
5337 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5340 /* Phase 3 - Flow Analysis - Flow Tree
5342 * In this phase, the individual flow blocks are examined
5343 * to determine their order of excution.
5346 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5350 /* Phase x - Flow Analysis - Used Banks
5352 * In this phase, the individual flow blocks are examined
5353 * to determine the Register Banks they use
5356 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5360 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5361 pCodeRegMapLiveRanges(pb);
5363 RemoveUnusedRegisters();
5365 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5366 pCodeRegOptimizeRegUsage(level);
5372 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5377 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5379 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5380 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5381 pcflow = pcflow->next) {
5383 FillFlow(PCFL(pcflow));
5388 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5390 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5391 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5392 pcflow = pcflow->next) {
5394 FlowStats(PCFL(pcflow));
5400 /*-----------------------------------------------------------------*/
5401 /* AnalyzeBanking - Called after the memory addresses have been */
5402 /* assigned to the registers. */
5404 /*-----------------------------------------------------------------*/
5406 void AnalyzeBanking(void)
5410 if(!picIsInitialized()) {
5411 // fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5412 // fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5413 // fprintf(stderr,"support/scripts/inc2h.pl\n");
5414 // fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5417 setDefMaxRam(); // Max RAM has not been included, so use default setting
5420 /* Phase x - Flow Analysis - Used Banks
5422 * In this phase, the individual flow blocks are examined
5423 * to determine the Register Banks they use
5429 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5430 // BanksUsedFlow(pb);
5431 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5432 FixRegisterBanking(pb,-1); // cur_bank is unknown
5436 /*-----------------------------------------------------------------*/
5437 /*-----------------------------------------------------------------*/
5438 DEFSETFUNC (resetrIdx)
5440 regs *r = (regs *)item;
5448 /*-----------------------------------------------------------------*/
5449 /* InitRegReuse - Initialises variables for code analyzer */
5450 /*-----------------------------------------------------------------*/
5452 void InitReuseReg(void)
5454 /* Find end of statically allocated variables for start idx */
5455 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5457 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5458 if (r->type != REG_SFR) {
5459 maxIdx += r->size; /* Increment for all statically allocated variables */
5463 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5466 /*-----------------------------------------------------------------*/
5467 /*-----------------------------------------------------------------*/
5468 static unsigned register_reassign(pBlock *pb, unsigned idx)
5472 /* check recursion */
5473 pc = setFirstItem(pb->function_entries);
5479 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5481 if (pb->tregisters) {
5483 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5484 if (r->type == REG_GPR) {
5486 if (r->rIdx < (int)idx) {
5489 if (peakIdx < idx) peakIdx = idx;
5490 sprintf(s,"r0x%02X", r->rIdx);
5491 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5493 r->name = Safe_strdup(s);
5499 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5501 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5502 char *dest = get_op_from_instruction(PCI(pc));
5504 pCode *pcn = findFunction(dest);
5506 register_reassign(pcn->pb,idx);
5515 /*------------------------------------------------------------------*/
5516 /* ReuseReg were call tree permits */
5518 /* Re-allocate the GPR for optimum reuse for a given pblock */
5519 /* eg if a function m() calls function f1() and f2(), where f1 */
5520 /* allocates a local variable vf1 and f2 allocates a local */
5521 /* variable vf2. Then providing f1 and f2 do not call each other */
5522 /* they may share the same general purpose registers for vf1 and */
5524 /* This is done by first setting the the regs rIdx to start after */
5525 /* all the global variables, then walking through the call tree */
5526 /* renaming the registers to match their new idx and incrementng */
5527 /* it as it goes. If a function has already been called it will */
5528 /* only rename the registers if it has already used up those */
5529 /* registers ie rIdx of the function's registers is lower than the */
5530 /* current rIdx. That way the register will not be reused while */
5531 /* still being used by an eariler function call. */
5533 /* Note for this to work the functions need to be declared static. */
5535 /*------------------------------------------------------------------*/
5540 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5541 /* Non static functions can be called from other modules so their registers must reassign */
5542 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5543 register_reassign(pb,peakIdx);
5547 /*-----------------------------------------------------------------*/
5548 /* buildCallTree - look at the flow and extract all of the calls */
5550 /*-----------------------------------------------------------------*/
5552 void buildCallTree(void )
5561 /* Now build the call tree.
5562 First we examine all of the pCodes for functions.
5563 Keep in mind that the function boundaries coincide
5564 with pBlock boundaries.
5566 The algorithm goes something like this:
5567 We have two nested loops. The outer loop iterates
5568 through all of the pBlocks/functions. The inner
5569 loop iterates through all of the pCodes for
5570 a given pBlock. When we begin iterating through
5571 a pBlock, the variable pc_fstart, pCode of the start
5572 of a function, is cleared. We then search for pCodes
5573 of type PC_FUNCTION. When one is encountered, we
5574 initialize pc_fstart to this and at the same time
5575 associate a new pBranch object that signifies a
5576 branch entry. If a return is found, then this signifies
5577 a function exit point. We'll link the pCodes of these
5578 returns to the matching pc_fstart.
5580 When we're done, a doubly linked list of pBranches
5581 will exist. The head of this list is stored in
5582 `the_pFile', which is the meta structure for all
5583 of the pCode. Look at the printCallTree function
5584 on how the pBranches are linked together.
5587 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5588 pCode *pc_fstart=NULL;
5589 for(pc = pb->pcHead; pc; pc = pc->next) {
5591 pCodeFunction *pcf = PCF(pc);
5594 if(STRCASECMP(pcf->fname, "_main") == 0) {
5595 //fprintf(stderr," found main \n");
5596 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5600 pbr = Safe_calloc(1,sizeof(pBranch));
5601 pbr->pc = pc_fstart = pc;
5604 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5606 // Here's a better way of doing the same:
5607 addSet(&pb->function_entries, pc);
5610 // Found an exit point in a function, e.g. return
5611 // (Note, there may be more than one return per function)
5613 pBranchLink(PCF(pc_fstart), pcf);
5615 addSet(&pb->function_exits, pc);
5617 } else if(isCALL(pc)) {
5618 addSet(&pb->function_calls,pc);
5624 /*-----------------------------------------------------------------*/
5625 /* AnalyzepCode - parse the pCode that has been generated and form */
5626 /* all of the logical connections. */
5628 /* Essentially what's done here is that the pCode flow is */
5630 /*-----------------------------------------------------------------*/
5632 void AnalyzepCode(char dbName)
5643 /* Phase 1 - Register allocation and peep hole optimization
5645 * The first part of the analysis is to determine the registers
5646 * that are used in the pCode. Once that is done, the peep rules
5647 * are applied to the code. We continue to loop until no more
5648 * peep rule optimizations are found (or until we exceed the
5649 * MAX_PASSES threshold).
5651 * When done, the required registers will be determined.
5657 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5659 /* First, merge the labels with the instructions */
5660 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5661 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5663 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5664 pBlockMergeLabels(pb);
5667 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5671 changes = OptimizepCode(dbName);
5673 } while(changes && (i++ < MAX_PASSES));
5678 /*-----------------------------------------------------------------*/
5679 /* ispCodeFunction - returns true if *pc is the pCode of a */
5681 /*-----------------------------------------------------------------*/
5682 bool ispCodeFunction(pCode *pc)
5685 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5691 /*-----------------------------------------------------------------*/
5692 /* findFunction - Search for a function by name (given the name) */
5693 /* in the set of all functions that are in a pBlock */
5694 /* (note - I expect this to change because I'm planning to limit */
5695 /* pBlock's to just one function declaration */
5696 /*-----------------------------------------------------------------*/
5697 pCode *findFunction(char *fname)
5704 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5706 pc = setFirstItem(pb->function_entries);
5709 if((pc->type == PC_FUNCTION) &&
5711 (strcmp(fname, PCF(pc)->fname)==0))
5714 pc = setNextItem(pb->function_entries);
5722 void MarkUsedRegisters(set *regset)
5727 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5728 r2 = pic14_regWithIdx(r1->rIdx);
5736 void pBlockStats(FILE *of, pBlock *pb)
5742 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5744 // for now just print the first element of each set
5745 pc = setFirstItem(pb->function_entries);
5747 fprintf(of,";entry: ");
5750 pc = setFirstItem(pb->function_exits);
5752 fprintf(of,";has an exit\n");
5756 pc = setFirstItem(pb->function_calls);
5758 fprintf(of,";functions called:\n");
5761 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5762 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5764 pc = setNextItem(pb->function_calls);
5768 r = setFirstItem(pb->tregisters);
5770 int n = elementsInSet(pb->tregisters);
5772 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5775 fprintf(of,"; %s\n",r->name);
5776 r = setNextItem(pb->tregisters);
5781 /*-----------------------------------------------------------------*/
5782 /*-----------------------------------------------------------------*/
5784 static void sequencepCode(void)
5790 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5792 pb->seq = GpCodeSequenceNumber+1;
5794 for( pc = pb->pcHead; pc; pc = pc->next)
5795 pc->seq = ++GpCodeSequenceNumber;
5801 /*-----------------------------------------------------------------*/
5802 /*-----------------------------------------------------------------*/
5804 set *register_usage(pBlock *pb)
5807 set *registers=NULL;
5808 set *registersInCallPath = NULL;
5810 / * check recursion * /
5812 pc = setFirstItem(pb->function_entries);
5819 if(pc->type != PC_FUNCTION)
5820 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5822 pc = setFirstItem(pb->function_calls);
5823 for( ; pc; pc = setNextItem(pb->function_calls)) {
5825 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5826 char *dest = get_op_from_instruction(PCI(pc));
5828 pcn = findFunction(dest);
5830 registersInCallPath = register_usage(pcn->pb);
5832 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5837 pBlockStats(stderr,pb); // debug
5840 // Mark the registers in this block as used.
5842 MarkUsedRegisters(pb->tregisters);
5843 if(registersInCallPath) {
5844 / * registers were used in the functions this pBlock has called * /
5845 / * so now, we need to see if these collide with the ones we are * /
5848 regs *r1,*r2, *newreg;
5850 DFPRINTF((stderr,"comparing registers\n"));
5852 r1 = setFirstItem(registersInCallPath);
5854 if (r1->type != REG_STK) {
5855 r2 = setFirstItem(pb->tregisters);
5857 while(r2 && (r2->type != REG_STK)) {
5859 if(r2->rIdx == r1->rIdx) {
5860 newreg = pic14_findFreeReg(REG_GPR);
5864 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5868 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5869 r1->rIdx, newreg->rIdx));
5870 r2->rIdx = newreg->rIdx;
5872 r2->name = Safe_strdup(newreg->name);
5876 newreg->wasUsed = 1;
5878 r2 = setNextItem(pb->tregisters);
5882 r1 = setNextItem(registersInCallPath);
5885 / * Collisions have been resolved. Now free the registers in the call path * /
5886 r1 = setFirstItem(registersInCallPath);
5888 newreg = pic14_regWithIdx(r1->rIdx);
5889 if (newreg) newreg->isFree = 1;
5890 r1 = setNextItem(registersInCallPath);
5894 // MarkUsedRegisters(pb->registers);
5896 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5899 DFPRINTF((stderr,"returning regs\n"));
5901 DFPRINTF((stderr,"not returning regs\n"));
5903 DFPRINTF((stderr,"pBlock after register optim.\n"));
5904 pBlockStats(stderr,pb); // debug
5911 /*-----------------------------------------------------------------*/
5912 /* printCallTree - writes the call tree to a file */
5914 /*-----------------------------------------------------------------*/
5915 void pct2(FILE *of,pBlock *pb,int indent)
5919 // set *registersInCallPath = NULL;
5925 return; //recursion ?
5927 pc = setFirstItem(pb->function_entries);
5934 for(i=0;i<indent;i++) // Indentation
5937 if(pc->type == PC_FUNCTION)
5938 fprintf(of,"%s\n",PCF(pc)->fname);
5943 pc = setFirstItem(pb->function_calls);
5944 for( ; pc; pc = setNextItem(pb->function_calls)) {
5946 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5947 char *dest = get_op_from_instruction(PCI(pc));
5949 pcn = findFunction(dest);
5951 pct2(of,pcn->pb,indent+1);
5953 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5961 /*-----------------------------------------------------------------*/
5962 /* printCallTree - writes the call tree to a file */
5964 /*-----------------------------------------------------------------*/
5966 void printCallTree(FILE *of)
5978 fprintf(of, "\npBlock statistics\n");
5979 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5984 fprintf(of,"Call Tree\n");
5985 pbr = the_pFile->functions;
5989 if(!ispCodeFunction(pc))
5990 fprintf(of,"bug in call tree");
5993 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5995 while(pc->next && !ispCodeFunction(pc->next)) {
5997 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5998 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6006 fprintf(of,"\n**************\n\na better call tree\n");
6007 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6012 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6013 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6019 /*-----------------------------------------------------------------*/
6021 /*-----------------------------------------------------------------*/
6023 void InlineFunction(pBlock *pb)
6031 pc = setFirstItem(pb->function_calls);
6033 for( ; pc; pc = setNextItem(pb->function_calls)) {
6036 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6037 pCode *pcp = pc->prev;
6043 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1) && !PCF(pcn)->isPublic && (pcp && (isPCI_BITSKIP(pcp)||!isPCI_SKIP(pcp)))) { /* Bit skips can be inverted other skips can not */
6045 InlineFunction(pcn->pb);
6048 At this point, *pc points to a CALL mnemonic, and
6049 *pcn points to the function that is being called.
6051 To in-line this call, we need to remove the CALL
6052 and RETURN(s), and link the function pCode in with
6059 /* Check if previous instruction was a bit skip */
6060 if (isPCI_BITSKIP(pcp)) {
6062 /* Invert skip instruction and add a goto */
6063 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6065 if(isPCL(pc_call->next)) { // Label pcode
6066 pcl = PCL(pc_call->next);
6067 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6068 pcl = PCL(PCI(pc_call->next)->label->pc);
6070 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6071 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6073 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6076 /* remove callee pBlock from the pBlock linked list */
6077 removepBlock(pcn->pb);
6085 /* Remove the Function pCode */
6086 pct = findNextInstruction(pcn->next);
6088 /* Link the function with the callee */
6089 if (pcp) pcp->next = pcn->next;
6090 pcn->next->prev = pcp;
6092 /* Convert the function name into a label */
6094 pbr = Safe_calloc(1,sizeof(pBranch));
6095 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6097 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6098 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6100 /* turn all of the return's except the last into goto's */
6101 /* check case for 2 instruction pBlocks */
6102 pce = findNextInstruction(pcn->next);
6104 pCode *pce_next = findNextInstruction(pce->next);
6106 if(pce_next == NULL) {
6107 /* found the last return */
6108 pCode *pc_call_next = findNextInstruction(pc_call->next);
6110 //fprintf(stderr,"found last return\n");
6111 //pce->print(stderr,pce);
6112 pce->prev->next = pc_call->next;
6113 pc_call->next->prev = pce->prev;
6114 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6123 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6129 /*-----------------------------------------------------------------*/
6131 /*-----------------------------------------------------------------*/
6133 void InlinepCode(void)
6142 if(!functionInlining)
6145 /* Loop through all of the function definitions and count the
6146 * number of times each one is called */
6147 //fprintf(stderr,"inlining %d\n",__LINE__);
6149 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6151 pc = setFirstItem(pb->function_calls);
6153 for( ; pc; pc = setNextItem(pb->function_calls)) {
6156 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6157 if(pcn && isPCF(pcn)) {
6158 PCF(pcn)->ncalled++;
6161 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6166 //fprintf(stderr,"inlining %d\n",__LINE__);
6168 /* Now, Loop through the function definitions again, but this
6169 * time inline those functions that have only been called once. */
6171 InlineFunction(the_pFile->pbHead);
6172 //fprintf(stderr,"inlining %d\n",__LINE__);
6174 for(pb = the_pFile->pbHead; pb; pb = pb->next)