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, "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);
1350 if ((unsigned)shareBankAddress > getMaxRam())
1351 shareBankAddress = (int)getMaxRam();
1353 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1354 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1355 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1356 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1357 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1358 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1360 pc_status.rIdx = IDX_STATUS;
1361 pc_fsr.rIdx = IDX_FSR;
1362 pc_indf.rIdx = IDX_INDF;
1363 pc_intcon.rIdx = IDX_INTCON;
1364 pc_pcl.rIdx = IDX_PCL;
1365 pc_pclath.rIdx = IDX_PCLATH;
1367 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. */
1368 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1369 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1371 pc_wsave.rIdx = pc_wsave.r->rIdx;
1372 pc_ssave.rIdx = pc_ssave.r->rIdx;
1373 pc_psave.rIdx = pc_psave.r->rIdx;
1375 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1376 pc_wsave.r->address = shareBankAddress-stkSize;
1377 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1378 pc_ssave.r->address = shareBankAddress-stkSize-1;
1379 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1380 pc_psave.r->address = shareBankAddress-stkSize-2;
1382 /* probably should put this in a separate initialization routine */
1383 pb_dead_pcodes = newpBlock();
1387 /*-----------------------------------------------------------------*/
1388 /* mnem2key - convert a pic mnemonic into a hash key */
1389 /* (BTW - this spreads the mnemonics quite well) */
1391 /*-----------------------------------------------------------------*/
1393 int mnem2key(char const *mnem)
1402 key += toupper(*mnem++) +1;
1406 return (key & 0x1f);
1410 void pic14initMnemonics(void)
1415 pCodeInstruction *pci;
1417 if(mnemonics_initialized)
1420 //FIXME - probably should NULL out the array before making the assignments
1421 //since we check the array contents below this initialization.
1423 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1424 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1425 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1426 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1427 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1428 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1429 pic14Mnemonics[POC_BCF] = &pciBCF;
1430 pic14Mnemonics[POC_BSF] = &pciBSF;
1431 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1432 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1433 pic14Mnemonics[POC_CALL] = &pciCALL;
1434 pic14Mnemonics[POC_COMF] = &pciCOMF;
1435 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1436 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1437 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1438 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1439 pic14Mnemonics[POC_DECF] = &pciDECF;
1440 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1441 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1442 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1443 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1444 pic14Mnemonics[POC_INCF] = &pciINCF;
1445 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1446 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1447 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1448 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1449 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1450 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1451 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1452 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1453 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1454 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1455 pic14Mnemonics[POC_NOP] = &pciNOP;
1456 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1457 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1458 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1459 pic14Mnemonics[POC_RLF] = &pciRLF;
1460 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1461 pic14Mnemonics[POC_RRF] = &pciRRF;
1462 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1463 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1464 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1465 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1466 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1467 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1468 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1469 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1470 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1471 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1472 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1473 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1475 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1476 if(pic14Mnemonics[i])
1477 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1478 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1481 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1482 pci = hTabNextItem(pic14MnemonicsHash, &key);
1485 mnemonics_initialized = 1;
1488 int getpCodePeepCommand(char *cmd);
1490 int getpCode(char *mnem,unsigned dest)
1493 pCodeInstruction *pci;
1494 int key = mnem2key(mnem);
1496 if(!mnemonics_initialized)
1497 pic14initMnemonics();
1499 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1503 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1504 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1508 pci = hTabNextItemWK (pic14MnemonicsHash);
1515 /*-----------------------------------------------------------------*
1516 * pic14initpCodePeepCommands
1518 *-----------------------------------------------------------------*/
1519 void pic14initpCodePeepCommands(void)
1527 hTabAddItem(&pic14pCodePeepCommandsHash,
1528 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1530 } while (peepCommands[i].cmd);
1532 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1535 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1536 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1541 /*-----------------------------------------------------------------
1544 *-----------------------------------------------------------------*/
1546 int getpCodePeepCommand(char *cmd)
1550 int key = mnem2key(cmd);
1553 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1556 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1557 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1561 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1568 char getpBlock_dbName(pBlock *pb)
1574 return pb->cmemmap->dbName;
1578 void pBlockConvert2ISR(pBlock *pb)
1589 /*-----------------------------------------------------------------*/
1590 /* movepBlock2Head - given the dbname of a pBlock, move all */
1591 /* instances to the front of the doubly linked */
1592 /* list of pBlocks */
1593 /*-----------------------------------------------------------------*/
1595 void movepBlock2Head(char dbName)
1602 pb = the_pFile->pbHead;
1606 if(getpBlock_dbName(pb) == dbName) {
1607 pBlock *pbn = pb->next;
1608 pb->next = the_pFile->pbHead;
1609 the_pFile->pbHead->prev = pb;
1610 the_pFile->pbHead = pb;
1613 pb->prev->next = pbn;
1615 // If the pBlock that we just moved was the last
1616 // one in the link of all of the pBlocks, then we
1617 // need to point the tail to the block just before
1618 // the one we moved.
1619 // Note: if pb->next is NULL, then pb must have
1620 // been the last pBlock in the chain.
1623 pbn->prev = pb->prev;
1625 the_pFile->pbTail = pb->prev;
1636 void copypCode(FILE *of, char dbName)
1640 if(!of || !the_pFile)
1643 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1644 if(getpBlock_dbName(pb) == dbName) {
1652 void pcode_test(void)
1655 DFPRINTF((stderr,"pcode is alive!\n"));
1665 /* create the file name */
1666 strcpy(buffer,dstFileName);
1667 strcat(buffer,".p");
1669 if( !(pFile = fopen(buffer, "w" ))) {
1670 werror(E_FILE_OPEN_ERR,buffer);
1674 fprintf(pFile,"pcode dump\n\n");
1676 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1677 fprintf(pFile,"\n\tNew pBlock\n\n");
1679 fprintf(pFile,"%s",pb->cmemmap->sname);
1681 fprintf(pFile,"internal pblock");
1683 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1684 printpBlock(pFile,pb);
1688 /*-----------------------------------------------------------------*/
1689 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1690 /* ister, RegCond will return the bit being referenced. */
1692 /* fixme - why not just OR in the pcop bit field */
1693 /*-----------------------------------------------------------------*/
1695 static int RegCond(pCodeOp *pcop)
1701 if (pcop->type == PO_GPR_BIT) {
1702 char *name = pcop->name;
1704 name = PCOR(pcop)->r->name;
1705 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1706 switch(PCORB(pcop)->bit) {
1720 /*-----------------------------------------------------------------*/
1721 /* newpCode - create and return a newly initialized pCode */
1723 /* fixme - rename this */
1725 /* The purpose of this routine is to create a new Instruction */
1726 /* pCode. This is called by gen.c while the assembly code is being */
1730 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1731 /* (note that the op is analogous to but not the */
1732 /* same thing as the opcode of the instruction.) */
1733 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1736 /* a pointer to the new malloc'd pCode is returned. */
1740 /*-----------------------------------------------------------------*/
1741 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1743 pCodeInstruction *pci ;
1745 if(!mnemonics_initialized)
1746 pic14initMnemonics();
1748 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1750 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1751 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1752 pci->pc.id = PCodeID();
1755 if(pci->inCond & PCC_EXAMINE_PCOP)
1756 pci->inCond |= RegCond(pcop);
1758 if(pci->outCond & PCC_EXAMINE_PCOP)
1759 pci->outCond |= RegCond(pcop);
1761 pci->pc.prev = pci->pc.next = NULL;
1762 return (pCode *)pci;
1765 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1771 /*-----------------------------------------------------------------*/
1772 /* newpCodeWild - create a "wild" as in wild card pCode */
1774 /* Wild pcodes are used during the peep hole optimizer to serve */
1775 /* as place holders for any instruction. When a snippet of code is */
1776 /* compared to a peep hole rule, the wild card opcode will match */
1777 /* any instruction. However, the optional operand and label are */
1778 /* additional qualifiers that must also be matched before the */
1779 /* line (of assembly code) is declared matched. Note that the */
1780 /* operand may be wild too. */
1782 /* Note, a wild instruction is specified just like a wild var: */
1783 /* %4 ; A wild instruction, */
1784 /* See the peeph.def file for additional examples */
1786 /*-----------------------------------------------------------------*/
1788 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1793 pcw = Safe_calloc(1,sizeof(pCodeWild));
1795 pcw->pci.pc.type = PC_WILD;
1796 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1797 pcw->id = PCodeID();
1798 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1799 pcw->pci.pc.pb = NULL;
1801 // pcw->pci.pc.analyze = genericAnalyze;
1802 pcw->pci.pc.destruct = genericDestruct;
1803 pcw->pci.pc.print = genericPrint;
1805 pcw->id = pCodeID; // this is the 'n' in %n
1806 pcw->operand = optional_operand;
1807 pcw->label = optional_label;
1809 pcw->mustBeBitSkipInst = 0;
1810 pcw->mustNotBeBitSkipInst = 0;
1811 pcw->invertBitSkipInst = 0;
1813 return ( (pCode *)pcw);
1817 /*-----------------------------------------------------------------*/
1818 /* newPcodeInlineP - create a new pCode from a char string */
1819 /*-----------------------------------------------------------------*/
1822 pCode *newpCodeInlineP(char *cP)
1827 pcc = Safe_calloc(1,sizeof(pCodeComment));
1829 pcc->pc.type = PC_INLINE;
1830 pcc->pc.prev = pcc->pc.next = NULL;
1831 pcc->pc.id = PCodeID();
1832 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1835 // pcc->pc.analyze = genericAnalyze;
1836 pcc->pc.destruct = genericDestruct;
1837 pcc->pc.print = genericPrint;
1840 pcc->comment = Safe_strdup(cP);
1842 pcc->comment = NULL;
1844 return ( (pCode *)pcc);
1848 /*-----------------------------------------------------------------*/
1849 /* newPcodeCharP - create a new pCode from a char string */
1850 /*-----------------------------------------------------------------*/
1852 pCode *newpCodeCharP(char *cP)
1857 pcc = Safe_calloc(1,sizeof(pCodeComment));
1859 pcc->pc.type = PC_COMMENT;
1860 pcc->pc.prev = pcc->pc.next = NULL;
1861 pcc->pc.id = PCodeID();
1862 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1865 // pcc->pc.analyze = genericAnalyze;
1866 pcc->pc.destruct = genericDestruct;
1867 pcc->pc.print = genericPrint;
1870 pcc->comment = Safe_strdup(cP);
1872 pcc->comment = NULL;
1874 return ( (pCode *)pcc);
1878 /*-----------------------------------------------------------------*/
1879 /* newpCodeFunction - */
1880 /*-----------------------------------------------------------------*/
1883 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1887 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1888 //_ALLOC(pcf,sizeof(pCodeFunction));
1890 pcf->pc.type = PC_FUNCTION;
1891 pcf->pc.prev = pcf->pc.next = NULL;
1892 pcf->pc.id = PCodeID();
1893 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1896 // pcf->pc.analyze = genericAnalyze;
1897 pcf->pc.destruct = genericDestruct;
1898 pcf->pc.print = pCodePrintFunction;
1903 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1904 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1905 strcpy(pcf->modname,mod);
1907 pcf->modname = NULL;
1910 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1911 pcf->fname = Safe_calloc(1,strlen(f)+1);
1912 strcpy(pcf->fname,f);
1916 pcf->isPublic = (unsigned)isPublic;
1918 return ( (pCode *)pcf);
1922 /*-----------------------------------------------------------------*/
1924 /*-----------------------------------------------------------------*/
1925 void destructpCodeFlow(pCode *pc)
1927 if(!pc || !isPCFL(pc))
1936 deleteSet(&PCFL(pc)->registers);
1937 deleteSet(&PCFL(pc)->from);
1938 deleteSet(&PCFL(pc)->to);
1943 pCode *newpCodeFlow(void )
1947 //_ALLOC(pcflow,sizeof(pCodeFlow));
1948 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1950 pcflow->pc.type = PC_FLOW;
1951 pcflow->pc.prev = pcflow->pc.next = NULL;
1952 pcflow->pc.pb = NULL;
1954 // pcflow->pc.analyze = genericAnalyze;
1955 pcflow->pc.destruct = destructpCodeFlow;
1956 pcflow->pc.print = genericPrint;
1958 pcflow->pc.seq = GpcFlowSeq++;
1960 pcflow->from = pcflow->to = NULL;
1962 pcflow->inCond = PCC_NONE;
1963 pcflow->outCond = PCC_NONE;
1965 pcflow->firstBank = 'U'; /* Undetermined */
1966 pcflow->lastBank = 'U'; /* Undetermined */
1968 pcflow->FromConflicts = 0;
1969 pcflow->ToConflicts = 0;
1973 pcflow->registers = newSet();
1975 return ( (pCode *)pcflow);
1979 /*-----------------------------------------------------------------*/
1980 /*-----------------------------------------------------------------*/
1981 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1983 pCodeFlowLink *pcflowLink;
1985 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1987 pcflowLink->pcflow = pcflow;
1988 pcflowLink->bank_conflict = 0;
1993 /*-----------------------------------------------------------------*/
1994 /* newpCodeCSource - create a new pCode Source Symbol */
1995 /*-----------------------------------------------------------------*/
1997 pCode *newpCodeCSource(int ln, char *f, char *l)
2002 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2004 pccs->pc.type = PC_CSOURCE;
2005 pccs->pc.prev = pccs->pc.next = NULL;
2006 pccs->pc.id = PCodeID();
2009 pccs->pc.destruct = genericDestruct;
2010 pccs->pc.print = genericPrint;
2012 pccs->line_number = ln;
2014 pccs->line = Safe_strdup(l);
2019 pccs->file_name = Safe_strdup(f);
2021 pccs->file_name = NULL;
2023 return ( (pCode *)pccs);
2027 /*******************************************************************/
2028 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2029 /* added by VR 6-Jun-2003 */
2030 /*******************************************************************/
2032 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2039 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2040 pcad->pci.pc.type = PC_ASMDIR;
2041 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2042 pcad->pci.pc.pb = NULL;
2043 pcad->pci.pc.destruct = genericDestruct;
2044 pcad->pci.pc.print = genericPrint;
2046 if(asdir && *asdir) {
2048 while(isspace(*asdir))asdir++; // strip any white space from the beginning
2050 pcad->directive = Safe_strdup( asdir );
2053 va_start(ap, argfmt);
2055 memset(buffer, 0, sizeof(buffer));
2056 if(argfmt && *argfmt)
2057 vsprintf(buffer, argfmt, ap);
2061 while(isspace(*lbp))lbp++;
2064 pcad->arg = Safe_strdup( lbp );
2066 return ((pCode *)pcad);
2069 /*-----------------------------------------------------------------*/
2070 /* pCodeLabelDestruct - free memory used by a label. */
2071 /*-----------------------------------------------------------------*/
2072 static void pCodeLabelDestruct(pCode *pc)
2078 if((pc->type == PC_LABEL) && PCL(pc)->label)
2079 free(PCL(pc)->label);
2085 pCode *newpCodeLabel(char *name, int key)
2091 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2093 pcl->pc.type = PC_LABEL;
2094 pcl->pc.prev = pcl->pc.next = NULL;
2095 pcl->pc.id = PCodeID();
2096 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2099 // pcl->pc.analyze = genericAnalyze;
2100 pcl->pc.destruct = pCodeLabelDestruct;
2101 pcl->pc.print = pCodePrintLabel;
2107 sprintf(s,"_%05d_DS_",key);
2112 pcl->label = Safe_strdup(s);
2114 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2115 return ( (pCode *)pcl);
2120 /*-----------------------------------------------------------------*/
2121 /* newpBlock - create and return a pointer to a new pBlock */
2122 /*-----------------------------------------------------------------*/
2123 pBlock *newpBlock(void)
2128 PpB = Safe_calloc(1,sizeof(pBlock) );
2129 PpB->next = PpB->prev = NULL;
2131 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2132 PpB->tregisters = NULL;
2134 PpB->FlowTree = NULL;
2140 /*-----------------------------------------------------------------*/
2141 /* newpCodeChain - create a new chain of pCodes */
2142 /*-----------------------------------------------------------------*
2144 * This function will create a new pBlock and the pointer to the
2145 * pCode that is passed in will be the first pCode in the block.
2146 *-----------------------------------------------------------------*/
2149 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2152 pBlock *pB = newpBlock();
2154 pB->pcHead = pB->pcTail = pc;
2161 /*-----------------------------------------------------------------*/
2162 /* newpCodeOpLabel - Create a new label given the key */
2163 /* Note, a negative key means that the label is part of wild card */
2164 /* (and hence a wild card label) used in the pCodePeep */
2165 /* optimizations). */
2166 /*-----------------------------------------------------------------*/
2168 pCodeOp *newpCodeOpLabel(char *name, int key)
2171 static int label_key=-1;
2175 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2176 pcop->type = PO_LABEL;
2181 sprintf(s=buffer,"_%05d_DS_",key);
2183 s = name, key = label_key--;
2185 PCOLAB(pcop)->offset = 0;
2187 pcop->name = Safe_strdup(s);
2189 ((pCodeOpLabel *)pcop)->key = key;
2191 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2195 /*-----------------------------------------------------------------*/
2196 /*-----------------------------------------------------------------*/
2197 pCodeOp *newpCodeOpLit(int lit)
2203 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2204 pcop->type = PO_LITERAL;
2208 sprintf(s,"0x%02x",lit);
2210 pcop->name = Safe_strdup(s);
2213 ((pCodeOpLit *)pcop)->lit = lit;
2218 /*-----------------------------------------------------------------*/
2219 /*-----------------------------------------------------------------*/
2220 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2224 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2225 pcop->type = PO_IMMEDIATE;
2228 pcop->name = Safe_strdup(name);
2231 r = dirregWithName(name);
2235 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2236 PCOI(pcop)->rIdx = r->rIdx;
2238 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2239 PCOI(pcop)->rIdx = -1;
2241 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2246 PCOI(pcop)->index = index;
2247 PCOI(pcop)->offset = offset;
2248 PCOI(pcop)->_const = code_space;
2249 PCOI(pcop)->_function = is_func;
2254 /*-----------------------------------------------------------------*/
2255 /*-----------------------------------------------------------------*/
2256 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2262 if(!pcwb || !subtype) {
2263 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2267 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2268 pcop->type = PO_WILD;
2269 sprintf(s,"%%%d",id);
2270 pcop->name = Safe_strdup(s);
2272 PCOW(pcop)->id = id;
2273 PCOW(pcop)->pcwb = pcwb;
2274 PCOW(pcop)->subtype = subtype;
2275 PCOW(pcop)->matched = NULL;
2279 /*-----------------------------------------------------------------*/
2280 /* Find a symbol with matching name */
2281 /*-----------------------------------------------------------------*/
2282 static symbol *symFindWithName(memmap * map, const char *name)
2286 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2287 if (sym->rname && (strcmp(sym->rname,name)==0))
2293 /*-----------------------------------------------------------------*/
2294 /*-----------------------------------------------------------------*/
2295 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2300 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2301 pcop->type = PO_GPR_BIT;
2303 PCORB(pcop)->bit = ibit;
2304 PCORB(pcop)->inBitSpace = inBitSpace;
2306 if (name) r = regFindWithName(name);
2308 // Register has not been allocated - check for symbol information
2310 sym = symFindWithName(bit, name);
2311 if (!sym) sym = symFindWithName(sfrbit, name);
2312 if (!sym) sym = symFindWithName(sfr, name);
2314 r = allocNewDirReg(sym->etype,name);
2320 PCOR(pcop)->rIdx = r->rIdx;
2322 pcop->name = Safe_strdup(name);
2323 PCOR(pcop)->r = NULL;
2324 PCOR(pcop)->rIdx = 0;
2329 /*-----------------------------------------------------------------*
2330 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2332 * If rIdx >=0 then a specific register from the set of registers
2333 * will be selected. If rIdx <0, then a new register will be searched
2335 *-----------------------------------------------------------------*/
2337 pCodeOp *newpCodeOpReg(int rIdx)
2341 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2346 PCOR(pcop)->rIdx = rIdx;
2347 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2349 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2352 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2356 pcop->type = PCOR(pcop)->r->pc_type;
2361 pCodeOp *newpCodeOpRegFromStr(char *name)
2365 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2366 PCOR(pcop)->r = allocRegByName(name, 1);
2367 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2368 pcop->type = PCOR(pcop)->r->pc_type;
2369 pcop->name = PCOR(pcop)->r->name;
2374 pCodeOp *newpCodeOpStr(char *name)
2378 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2379 pcop->type = PO_STR;
2380 pcop->name = Safe_strdup(name);
2382 PCOS(pcop)->isPublic = 0;
2388 /*-----------------------------------------------------------------*/
2389 /*-----------------------------------------------------------------*/
2391 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2398 pcop = newpCodeOpBit(name, -1,0);
2402 pcop = newpCodeOpLit(-1);
2406 pcop = newpCodeOpLabel(NULL,-1);
2410 pcop = newpCodeOpReg(-1);
2413 case PO_GPR_POINTER:
2414 case PO_GPR_REGISTER:
2416 pcop = newpCodeOpRegFromStr(name);
2418 pcop = newpCodeOpReg(-1);
2422 pcop = newpCodeOpStr(name);
2426 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2429 pcop->name = Safe_strdup(name);
2437 /*-----------------------------------------------------------------*/
2438 /*-----------------------------------------------------------------*/
2439 void pCodeConstString(char *name, char *value)
2443 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2448 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2452 sprintf(buffer,"; %s = %s",name,value);
2454 addpCode2pBlock(pb,newpCodeCharP(buffer));
2455 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2458 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2464 /*-----------------------------------------------------------------*/
2465 /*-----------------------------------------------------------------*/
2466 void pCodeReadCodeTable(void)
2470 fprintf(stderr, " %s\n",__FUNCTION__);
2472 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2476 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2477 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2478 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2479 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2481 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2482 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2483 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2484 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2489 /*-----------------------------------------------------------------*/
2490 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2491 /*-----------------------------------------------------------------*/
2492 void addpCode2pBlock(pBlock *pb, pCode *pc)
2499 /* If this is the first pcode to be added to a block that
2500 * was initialized with a NULL pcode, then go ahead and
2501 * make this pcode the head and tail */
2502 pb->pcHead = pb->pcTail = pc;
2505 pb->pcTail->next = pc;
2507 pc->prev = pb->pcTail;
2514 /*-----------------------------------------------------------------*/
2515 /* addpBlock - place a pBlock into the pFile */
2516 /*-----------------------------------------------------------------*/
2517 void addpBlock(pBlock *pb)
2519 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2522 /* First time called, we'll pass through here. */
2523 //_ALLOC(the_pFile,sizeof(pFile));
2524 the_pFile = Safe_calloc(1,sizeof(pFile));
2525 the_pFile->pbHead = the_pFile->pbTail = pb;
2526 the_pFile->functions = NULL;
2530 the_pFile->pbTail->next = pb;
2531 pb->prev = the_pFile->pbTail;
2533 the_pFile->pbTail = pb;
2536 /*-----------------------------------------------------------------*/
2537 /* removepBlock - remove a pBlock from the pFile */
2538 /*-----------------------------------------------------------------*/
2539 void removepBlock(pBlock *pb)
2547 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2549 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2552 if(pbs == the_pFile->pbHead)
2553 the_pFile->pbHead = pbs->next;
2555 if (pbs == the_pFile->pbTail)
2556 the_pFile->pbTail = pbs->prev;
2559 pbs->next->prev = pbs->prev;
2562 pbs->prev->next = pbs->next;
2569 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2573 /*-----------------------------------------------------------------*/
2574 /* printpCode - write the contents of a pCode to a file */
2575 /*-----------------------------------------------------------------*/
2576 void printpCode(FILE *of, pCode *pc)
2587 fprintf(of,"warning - unable to print pCode\n");
2590 /*-----------------------------------------------------------------*/
2591 /* printpBlock - write the contents of a pBlock to a file */
2592 /*-----------------------------------------------------------------*/
2593 void printpBlock(FILE *of, pBlock *pb)
2603 for(pc = pb->pcHead; pc; pc = pc->next)
2608 /*-----------------------------------------------------------------*/
2610 /* pCode processing */
2614 /*-----------------------------------------------------------------*/
2616 void unlinkpCode(pCode *pc)
2622 fprintf(stderr,"Unlinking: ");
2623 printpCode(stderr, pc);
2626 pc->prev->next = pc->next;
2628 pc->next->prev = pc->prev;
2630 pc->prev = pc->next = NULL;
2634 /*-----------------------------------------------------------------*/
2635 /*-----------------------------------------------------------------*/
2637 static void genericDestruct(pCode *pc)
2643 /* For instructions, tell the register (if there's one used)
2644 * that it's no longer needed */
2645 regs *reg = getRegFromInstruction(pc);
2647 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2650 /* Instead of deleting the memory used by this pCode, mark
2651 * the object as bad so that if there's a pointer to this pCode
2652 * dangling around somewhere then (hopefully) when the type is
2653 * checked we'll catch it.
2658 addpCode2pBlock(pb_dead_pcodes, pc);
2665 /*-----------------------------------------------------------------*/
2666 /* Copies the pCodeInstruction flow pointer from source pCode */
2667 /*-----------------------------------------------------------------*/
2668 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2670 pCodeFlow *pcflow = 0;
2671 for (p=pcs; p; p=p->prev) {
2673 pcflow = PCI(p)->pcflow;
2677 pcflow = (pCodeFlow*)p;
2681 PCI(pcd)->pcflow = pcflow;
2684 /*-----------------------------------------------------------------*/
2685 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2686 /* into the pCode chain containing pc1 */
2687 /*-----------------------------------------------------------------*/
2688 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2694 pc2->next = pc1->next;
2696 pc1->next->prev = pc2;
2702 /* If this is an instrution type propogate the flow */
2704 CopyFlow(PCI(pc2),pc1);
2707 /*------------------------------------------------------------------*/
2708 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2709 /* into the pCode chain containing pc1 */
2710 /*------------------------------------------------------------------*/
2711 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2717 pc2->prev = pc1->prev;
2719 pc1->prev->next = pc2;
2725 /* If this is an instrution type propogate the flow */
2727 CopyFlow(PCI(pc2),pc1);
2730 /*-----------------------------------------------------------------*/
2731 /* pCodeOpCopy - copy a pcode operator */
2732 /*-----------------------------------------------------------------*/
2733 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2735 pCodeOp *pcopnew=NULL;
2740 switch(pcop->type) {
2743 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2744 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2745 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2746 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2751 /* Here we expand the wild card into the appropriate type: */
2752 /* By recursively calling pCodeOpCopy */
2753 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2754 if(PCOW(pcop)->matched)
2755 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2758 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2759 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2760 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2767 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2768 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2769 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2773 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2774 PCOI(pcopnew)->index = PCOI(pcop)->index;
2775 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2776 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2777 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2781 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2782 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2783 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2788 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2789 PCOR(pcopnew)->r = PCOR(pcop)->r;
2790 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2791 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2795 case PO_GPR_POINTER:
2796 case PO_GPR_REGISTER:
2800 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2801 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2802 PCOR(pcopnew)->r = PCOR(pcop)->r;
2803 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2804 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2805 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2809 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2810 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2811 PCOR(pcopnew)->r = PCOR(pcop)->r;
2812 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2813 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2816 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2817 case PO_SFR_REGISTER:
2825 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2826 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2830 pcopnew->type = pcop->type;
2832 pcopnew->name = Safe_strdup(pcop->name);
2834 pcopnew->name = NULL;
2839 /*-----------------------------------------------------------------*/
2840 /* popCopyReg - copy a pcode operator */
2841 /*-----------------------------------------------------------------*/
2842 pCodeOp *popCopyReg(pCodeOpReg *pc)
2846 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2847 pcor->pcop.type = pc->pcop.type;
2849 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2850 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2852 pcor->pcop.name = NULL;
2854 if (pcor->pcop.type == PO_IMMEDIATE){
2855 PCOL(pcor)->lit = PCOL(pc)->lit;
2858 pcor->rIdx = pc->rIdx;
2862 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2867 /*-----------------------------------------------------------------*/
2868 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2869 /*-----------------------------------------------------------------*/
2870 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2872 pCodeInstruction *new_pci;
2875 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2877 new_pci = PCI(newpCode(pci->op,pci->pcop));
2879 new_pci->pc.pb = pci->pc.pb;
2880 new_pci->from = pci->from;
2881 new_pci->to = pci->to;
2882 new_pci->label = pci->label;
2883 new_pci->pcflow = pci->pcflow;
2885 return PCODE(new_pci);
2888 /*-----------------------------------------------------------------*/
2889 /*-----------------------------------------------------------------*/
2890 void pCodeDeleteChain(pCode *f,pCode *t)
2895 DFPRINTF((stderr,"delete pCode:\n"));
2897 //f->print(stderr,f);
2898 //f->delete(f); this dumps core...
2903 /*-----------------------------------------------------------------*/
2904 /*-----------------------------------------------------------------*/
2905 void pBlockRegs(FILE *of, pBlock *pb)
2910 r = setFirstItem(pb->tregisters);
2912 r = setNextItem(pb->tregisters);
2917 /*-----------------------------------------------------------------*/
2918 /*-----------------------------------------------------------------*/
2919 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2924 int use_buffer = 1; // copy the string to the passed buffer pointer
2929 use_buffer = 0; // Don't bother copying the string to the buffer.
2933 switch(pcop->type) {
2937 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2940 //return PCOR(pcop)->r->name;
2944 if (PCOR(pcop)->r->type == REG_STK)
2945 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2947 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2950 SAFE_snprintf(&buffer,&size,"%s",r->name);
2960 if(PCOI(pcop)->_const) {
2962 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2963 switch(PCOI(pcop)->offset) {
2965 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2968 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2971 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2974 8 * PCOI(pcop)->offset );
2977 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2980 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2981 SAFE_snprintf(&s,&size,"(%s + %d)",
2983 PCOI(pcop)->index );
2985 switch(PCOI(pcop)->offset) {
2987 SAFE_snprintf(&s,&size,"%s",pcop->name);
2990 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2993 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3002 //size = sizeof(buffer);
3003 if( PCOR(pcop)->instance) {
3004 SAFE_snprintf(&s,&size,"(%s + %d)",
3006 PCOR(pcop)->instance );
3007 //fprintf(stderr,"PO_DIR %s\n",buffer);
3009 SAFE_snprintf(&s,&size,"%s",pcop->name);
3015 if(PCOLAB(pcop)->offset == 1)
3016 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3018 SAFE_snprintf(&s,&size,"%s",pcop->name);
3025 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3028 return PCOR(pcop)->r->name;
3031 /* fall through to the default case */
3035 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3043 printf("PIC port internal warning: (%s:%d) %s not found\n",
3048 return "NO operand";
3052 /*-----------------------------------------------------------------*/
3053 /*-----------------------------------------------------------------*/
3054 static char *get_op_from_instruction( pCodeInstruction *pcc)
3058 return get_op(pcc->pcop,NULL,0);
3060 return ("ERROR Null: get_op_from_instruction");
3064 /*-----------------------------------------------------------------*/
3065 /*-----------------------------------------------------------------*/
3066 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3068 fprintf(of,"pcodeopprint- not implemented\n");
3071 /*-----------------------------------------------------------------*/
3072 /* pCode2str - convert a pCode instruction to string */
3073 /*-----------------------------------------------------------------*/
3074 char *pCode2str(char *str, size_t size, pCode *pc)
3082 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3084 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3086 if(PCI(pc)->isBitInst) {
3087 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3088 char *name = PCI(pc)->pcop->name;
3090 name = PCOR(PCI(pc)->pcop)->r->name;
3091 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3092 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3094 SAFE_snprintf(&s,&size,"%s,%d", name,
3095 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3096 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3097 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3099 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3100 //PCI(pc)->pcop->t.bit );
3102 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3103 if( PCI(pc)->num_ops == 2)
3104 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3106 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3108 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3109 if( PCI(pc)->num_ops == 2)
3110 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3117 /* assuming that comment ends with a \n */
3118 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3122 /* assuming that inline code ends with a \n */
3123 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3127 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3130 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3133 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3136 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3139 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3142 if(PCAD(pc)->directive) {
3143 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3144 } else if(PCAD(pc)->arg) {
3145 /* special case to handle inline labels without a tab */
3146 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3151 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3157 /*-----------------------------------------------------------------*/
3158 /* genericPrint - the contents of a pCode to a file */
3159 /*-----------------------------------------------------------------*/
3160 static void genericPrint(FILE *of, pCode *pc)
3167 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3171 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3175 // If the opcode has a label, print that first
3178 pCodeInstruction *pci = PCI(pc);
3179 pBranch *pbl = pci->label;
3180 while(pbl && pbl->pc) {
3181 if(pbl->pc->type == PC_LABEL)
3182 pCodePrintLabel(of, pbl->pc);
3187 genericPrint(of,PCODE(pci->cline));
3190 pCode2str(str, 256, pc);
3192 fprintf(of,"%s",str);
3196 pCodeOpReg *pcor = PCOR(pci->pcop);
3197 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3199 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3200 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3201 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3206 pBranch *dpb = pc->to; // debug
3208 switch ( dpb->pc->type) {
3210 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3213 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3216 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3219 fprintf(of, "\t;flow");
3233 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3234 if(PCW(pc)->pci.label)
3235 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3237 if(PCW(pc)->operand) {
3238 fprintf(of,";\toperand ");
3239 pCodeOpPrint(of,PCW(pc)->operand );
3245 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3246 if(PCFL(pc)->ancestor)
3247 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3253 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3258 pBranch *pbl = PCAD(pc)->pci.label;
3259 while(pbl && pbl->pc) {
3260 if(pbl->pc->type == PC_LABEL)
3261 pCodePrintLabel(of, pbl->pc);
3265 if(PCAD(pc)->directive) {
3266 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3269 /* special case to handle inline labels without tab */
3270 fprintf(of, "%s\n", PCAD(pc)->arg);
3276 fprintf(of,"unknown pCode type %d\n",pc->type);
3280 /*-----------------------------------------------------------------*/
3281 /* pCodePrintFunction - prints function begin/end */
3282 /*-----------------------------------------------------------------*/
3284 static void pCodePrintFunction(FILE *of, pCode *pc)
3290 if( ((pCodeFunction *)pc)->modname)
3291 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3293 if(PCF(pc)->fname) {
3294 pBranch *exits = PCF(pc)->to;
3296 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3299 exits = exits->next;
3302 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3305 if((PCF(pc)->from &&
3306 PCF(pc)->from->pc->type == PC_FUNCTION &&
3307 PCF(PCF(pc)->from->pc)->fname) )
3308 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3310 fprintf(of,"; exit point [can't find entry point]\n");
3313 /*-----------------------------------------------------------------*/
3314 /* pCodePrintLabel - prints label */
3315 /*-----------------------------------------------------------------*/
3317 static void pCodePrintLabel(FILE *of, pCode *pc)
3324 fprintf(of,"%s\n",PCL(pc)->label);
3325 else if (PCL(pc)->key >=0)
3326 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3328 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3332 /*-----------------------------------------------------------------*/
3333 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3334 /* remove it if it is found. */
3335 /*-----------------------------------------------------------------*/
3336 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3342 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3343 b = PCI(pcl)->label;
3345 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3349 //fprintf (stderr, "%s \n",__FUNCTION__);
3350 //pcl->print(stderr,pcl);
3351 //pc->print(stderr,pc);
3354 //fprintf (stderr, "found label\n");
3358 bprev->next = b->next; /* Not first pCode in chain */
3362 PCI(pcl)->label = b->next; /* First pCode in chain */
3365 return; /* A label can't occur more than once */
3372 /*-----------------------------------------------------------------*/
3373 /*-----------------------------------------------------------------*/
3374 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3393 /*-----------------------------------------------------------------*/
3394 /* pBranchLink - given two pcodes, this function will link them */
3395 /* together through their pBranches */
3396 /*-----------------------------------------------------------------*/
3397 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3401 // Declare a new branch object for the 'from' pCode.
3403 //_ALLOC(b,sizeof(pBranch));
3404 b = Safe_calloc(1,sizeof(pBranch));
3405 b->pc = PCODE(t); // The link to the 'to' pCode.
3408 f->to = pBranchAppend(f->to,b);
3410 // Now do the same for the 'to' pCode.
3412 //_ALLOC(b,sizeof(pBranch));
3413 b = Safe_calloc(1,sizeof(pBranch));
3417 t->from = pBranchAppend(t->from,b);
3422 /*-----------------------------------------------------------------*/
3423 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3425 /*-----------------------------------------------------------------*/
3426 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3439 /*-----------------------------------------------------------------*/
3440 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3441 /*-----------------------------------------------------------------*/
3442 static void pCodeUnlink(pCode *pc)
3447 if(!pc->prev || !pc->next) {
3448 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3452 /* first remove the pCode from the chain */
3453 pc->prev->next = pc->next;
3454 pc->next->prev = pc->prev;
3456 /* Now for the hard part... */
3458 /* Remove the branches */
3462 pc1 = pb1->pc; /* Get the pCode that branches to the
3463 * one we're unlinking */
3465 /* search for the link back to this pCode (the one we're
3467 if(pb2 = pBranchFind(pc1->to,pc)) {
3468 pb2->pc = pc->to->pc; // make the replacement
3470 /* if the pCode we're unlinking contains multiple 'to'
3471 * branches (e.g. this a skip instruction) then we need
3472 * to copy these extra branches to the chain. */
3474 pBranchAppend(pb2, pc->to->next);
3483 /*-----------------------------------------------------------------*/
3484 /*-----------------------------------------------------------------*/
3486 static void genericAnalyze(pCode *pc)
3496 // Go through the pCodes that are in pCode chain and link
3497 // them together through the pBranches. Note, the pCodes
3498 // are linked together as a contiguous stream like the
3499 // assembly source code lines. The linking here mimics this
3500 // except that comments are not linked in.
3502 pCode *npc = pc->next;
3504 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3505 pBranchLink(pc,npc);
3510 /* reached the end of the pcode chain without finding
3511 * an instruction we could link to. */
3515 fprintf(stderr,"analyze PC_FLOW\n");
3519 fprintf(stderr,";A bad pCode is being used\n");
3525 /*-----------------------------------------------------------------*/
3526 /*-----------------------------------------------------------------*/
3527 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3531 if(pc->type == PC_LABEL) {
3532 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3535 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3536 pbr = PCI(pc)->label;
3538 if(pbr->pc->type == PC_LABEL) {
3539 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3549 /*-----------------------------------------------------------------*/
3550 /*-----------------------------------------------------------------*/
3551 int checkLabel(pCode *pc)
3555 if(pc && isPCI(pc)) {
3556 pbr = PCI(pc)->label;
3558 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3568 /*-----------------------------------------------------------------*/
3569 /* findLabelinpBlock - Search the pCode for a particular label */
3570 /*-----------------------------------------------------------------*/
3571 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3578 for(pc = pb->pcHead; pc; pc = pc->next)
3579 if(compareLabel(pc,pcop_label))
3585 /*-----------------------------------------------------------------*/
3586 /* findLabel - Search the pCode for a particular label */
3587 /*-----------------------------------------------------------------*/
3588 pCode * findLabel(pCodeOpLabel *pcop_label)
3596 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3597 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3601 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3605 /*-----------------------------------------------------------------*/
3606 /* findNextpCode - given a pCode, find the next of type 'pct' */
3607 /* in the linked list */
3608 /*-----------------------------------------------------------------*/
3609 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3622 /*-----------------------------------------------------------------*/
3623 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3624 /* in the linked list */
3625 /*-----------------------------------------------------------------*/
3626 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3630 if(pc->type == pct) {
3632 static unsigned int stop;
3634 stop++; // Place break point here
3645 /*-----------------------------------------------------------------*/
3646 /* findNextInstruction - given a pCode, find the next instruction */
3647 /* in the linked list */
3648 /*-----------------------------------------------------------------*/
3649 pCode * findNextInstruction(pCode *pci)
3654 if((pc->type == PC_OPCODE)
3655 || (pc->type == PC_WILD)
3656 || (pc->type == PC_ASMDIR))
3660 fprintf(stderr,"findNextInstruction: ");
3661 printpCode(stderr, pc);
3666 //fprintf(stderr,"Couldn't find instruction\n");
3670 /*-----------------------------------------------------------------*/
3671 /* findNextInstruction - given a pCode, find the next instruction */
3672 /* in the linked list */
3673 /*-----------------------------------------------------------------*/
3674 pCode * findPrevInstruction(pCode *pci)
3680 if((pc->type == PC_OPCODE)
3681 || (pc->type == PC_WILD)
3682 || (pc->type == PC_ASMDIR))
3687 fprintf(stderr,"pic16_findPrevInstruction: ");
3688 printpCode(stderr, pc);
3693 //fprintf(stderr,"Couldn't find instruction\n");
3697 /*-----------------------------------------------------------------*/
3698 /* findFunctionEnd - given a pCode find the end of the function */
3699 /* that contains it */
3700 /*-----------------------------------------------------------------*/
3701 pCode * findFunctionEnd(pCode *pc)
3704 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3710 fprintf(stderr,"Couldn't find function end\n");
3715 /*-----------------------------------------------------------------*/
3716 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3717 /* instruction with which it is associated. */
3718 /*-----------------------------------------------------------------*/
3719 static void AnalyzeLabel(pCode *pc)
3728 static void AnalyzeGOTO(pCode *pc)
3731 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3735 static void AnalyzeSKIP(pCode *pc)
3738 pBranchLink(pc,findNextInstruction(pc->next));
3739 pBranchLink(pc,findNextInstruction(pc->next->next));
3743 static void AnalyzeRETURN(pCode *pc)
3746 // branch_link(pc,findFunctionEnd(pc->next));
3752 /*-----------------------------------------------------------------*/
3753 /*-----------------------------------------------------------------*/
3754 regs * getRegFromInstruction(pCode *pc)
3760 PCI(pc)->num_ops == 0 )
3763 switch(PCI(pc)->pcop->type) {
3766 return PCOR(PCI(pc)->pcop)->r;
3770 return PCOR(PCI(pc)->pcop)->r;
3773 r = PCOI(PCI(pc)->pcop)->r;
3776 return dirregWithName(PCI(pc)->pcop->name);
3779 r = PCOR(PCI(pc)->pcop)->r;
3782 return dirregWithName(PCI(pc)->pcop->name);
3784 case PO_GPR_REGISTER:
3786 r = PCOR(PCI(pc)->pcop)->r;
3789 return dirregWithName(PCI(pc)->pcop->name);
3801 /*-----------------------------------------------------------------*/
3802 /*-----------------------------------------------------------------*/
3804 void AnalyzepBlock(pBlock *pb)
3811 /* Find all of the registers used in this pBlock
3812 * by looking at each instruction and examining it's
3815 for(pc = pb->pcHead; pc; pc = pc->next) {
3817 /* Is this an instruction with operands? */
3818 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3820 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3821 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3823 /* Loop through all of the registers declared so far in
3824 this block and see if we find this one there */
3826 regs *r = setFirstItem(pb->tregisters);
3829 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3830 PCOR(PCI(pc)->pcop)->r = r;
3833 r = setNextItem(pb->tregisters);
3837 /* register wasn't found */
3838 //r = Safe_calloc(1, sizeof(regs));
3839 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3840 //addSet(&pb->tregisters, r);
3841 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3842 //PCOR(PCI(pc)->pcop)->r = r;
3843 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3845 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3848 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3849 if(PCOR(PCI(pc)->pcop)->r) {
3850 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3851 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3853 if(PCI(pc)->pcop->name)
3854 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3856 fprintf(stderr,"ERROR: NULL register\n");
3865 /*-----------------------------------------------------------------*/
3867 /*-----------------------------------------------------------------*/
3868 void InsertpFlow(pCode *pc, pCode **pflow)
3871 PCFL(*pflow)->end = pc;
3873 if(!pc || !pc->next)
3876 *pflow = newpCodeFlow();
3877 pCodeInsertAfter(pc, *pflow);
3880 /*-----------------------------------------------------------------*/
3881 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3882 /* the flow blocks. */
3884 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3885 * point the instruction flow changes.
3887 /*-----------------------------------------------------------------*/
3888 void BuildFlow(pBlock *pb)
3891 pCode *last_pci=NULL;
3898 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3899 /* Insert a pCodeFlow object at the beginning of a pBlock */
3901 InsertpFlow(pb->pcHead, &pflow);
3903 //pflow = newpCodeFlow(); /* Create a new Flow object */
3904 //pflow->next = pb->pcHead; /* Make the current head the next object */
3905 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3906 //pb->pcHead = pflow; /* Make the Flow object the head */
3909 for( pc = findNextInstruction(pb->pcHead);
3911 pc=findNextInstruction(pc)) {
3914 PCI(pc)->pcflow = PCFL(pflow);
3916 //fprintf(stderr," build: ");
3917 //pflow->print(stderr,pflow);
3919 if( PCI(pc)->isSkip) {
3921 /* The two instructions immediately following this one
3922 * mark the beginning of a new flow segment */
3924 while(pc && PCI(pc)->isSkip) {
3926 PCI(pc)->pcflow = PCFL(pflow);
3930 InsertpFlow(pc, &pflow);
3931 pc=findNextInstruction(pc->next);
3939 PCI(pc)->pcflow = PCFL(pflow);
3941 InsertpFlow(pc, &pflow);
3943 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3945 InsertpFlow(pc, &pflow);
3948 } else if (checkLabel(pc)) {
3950 /* This instruction marks the beginning of a
3951 * new flow segment */
3956 /* If the previous pCode is not a flow object, then
3957 * insert a new flow object. (This check prevents
3958 * two consecutive flow objects from being insert in
3959 * the case where a skip instruction preceeds an
3960 * instruction containing a label.) */
3962 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3963 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3965 PCI(pc)->pcflow = PCFL(pflow);
3972 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3974 PCFL(pflow)->end = pb->pcTail;
3977 /*-------------------------------------------------------------------*/
3978 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3979 /* the flow blocks. */
3981 * unBuildFlow removes pCodeFlow objects from a pCode chain
3983 /*-----------------------------------------------------------------*/
3984 void unBuildFlow(pBlock *pb)
3999 if(PCI(pc)->pcflow) {
4000 //free(PCI(pc)->pcflow);
4001 PCI(pc)->pcflow = NULL;
4004 } else if(isPCFL(pc) )
4013 /*-----------------------------------------------------------------*/
4014 /*-----------------------------------------------------------------*/
4015 void dumpCond(int cond)
4018 static char *pcc_str[] = {
4032 int ncond = sizeof(pcc_str) / sizeof(char *);
4035 fprintf(stderr, "0x%04X\n",cond);
4037 for(i=0,j=1; i<ncond; i++, j<<=1)
4039 fprintf(stderr, " %s\n",pcc_str[i]);
4043 /*-----------------------------------------------------------------*/
4044 /*-----------------------------------------------------------------*/
4045 void FlowStats(pCodeFlow *pcflow)
4053 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4055 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4058 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4063 fprintf(stderr, " FlowStats inCond: ");
4064 dumpCond(pcflow->inCond);
4065 fprintf(stderr, " FlowStats outCond: ");
4066 dumpCond(pcflow->outCond);
4070 /*-----------------------------------------------------------------*
4071 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4072 * if it affects the banking bits.
4074 * return: -1 == Banking bits are unaffected by this pCode.
4076 * return: > 0 == Banking bits are affected.
4078 * If the banking bits are affected, then the returned value describes
4079 * which bits are affected and how they're affected. The lower half
4080 * of the integer maps to the bits that are affected, the upper half
4081 * to whether they're set or cleared.
4083 *-----------------------------------------------------------------*/
4085 #define SET_BANK_BIT (1 << 16)
4086 #define CLR_BANK_BIT 0
4088 static int isBankInstruction(pCode *pc)
4096 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4098 // Check to see if the register banks are changing
4099 if(PCI(pc)->isModReg) {
4101 pCodeOp *pcop = PCI(pc)->pcop;
4102 switch(PCI(pc)->op) {
4105 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4106 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4107 return SET_BANK_BIT | PIC_RP0_BIT;
4110 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4111 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4112 return CLR_BANK_BIT | PIC_RP0_BIT;
4117 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4118 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4119 return CLR_BANK_BIT | PIC_RP1_BIT;
4121 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4122 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4123 return CLR_BANK_BIT | PIC_RP1_BIT;
4127 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4128 //genericPrint(stderr, pc);
4139 /*-----------------------------------------------------------------*/
4140 /*-----------------------------------------------------------------*/
4142 static void FillFlow(pCodeFlow *pcflow)
4150 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4152 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4155 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4162 isBankInstruction(pc);
4164 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4167 fprintf(stderr, " FillFlow - Bad end of flow\n");
4169 fprintf(stderr, " FillFlow - Ending flow with\n ");
4170 pc->print(stderr,pc);
4173 fprintf(stderr, " FillFlow inCond: ");
4174 dumpCond(pcflow->inCond);
4175 fprintf(stderr, " FillFlow outCond: ");
4176 dumpCond(pcflow->outCond);
4181 /*-----------------------------------------------------------------*/
4182 /*-----------------------------------------------------------------*/
4183 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4185 pCodeFlowLink *fromLink, *toLink;
4187 if(!from || !to || !to->pcflow || !from->pcflow)
4190 fromLink = newpCodeFlowLink(from->pcflow);
4191 toLink = newpCodeFlowLink(to->pcflow);
4193 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4194 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4198 /*-----------------------------------------------------------------*
4199 * void LinkFlow(pBlock *pb)
4201 * In BuildFlow, the PIC code has been partitioned into contiguous
4202 * non-branching segments. In LinkFlow, we determine the execution
4203 * order of these segments. For example, if one of the segments ends
4204 * with a skip, then we know that there are two possible flow segments
4205 * to which control may be passed.
4206 *-----------------------------------------------------------------*/
4207 void LinkFlow(pBlock *pb)
4213 //fprintf(stderr,"linkflow \n");
4215 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4217 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4220 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4222 //fprintf(stderr," link: ");
4223 //pcflow->print(stderr,pcflow);
4225 //FillFlow(PCFL(pcflow));
4227 pc = PCFL(pcflow)->end;
4229 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4230 if(isPCI_SKIP(pc)) {
4231 //fprintf(stderr, "ends with skip\n");
4232 //pc->print(stderr,pc);
4233 pct=findNextInstruction(pc->next);
4234 LinkFlow_pCode(PCI(pc),PCI(pct));
4235 pct=findNextInstruction(pct->next);
4236 LinkFlow_pCode(PCI(pc),PCI(pct));
4240 if(isPCI_BRANCH(pc)) {
4241 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4243 //fprintf(stderr, "ends with branch\n ");
4244 //pc->print(stderr,pc);
4246 if(!(pcol && isPCOLAB(pcol))) {
4247 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4248 pc->print(stderr,pc);
4249 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4254 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4255 LinkFlow_pCode(PCI(pc),PCI(pct));
4257 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4258 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4259 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4265 //fprintf(stderr, "ends with non-branching instruction:\n");
4266 //pc->print(stderr,pc);
4268 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4274 //fprintf(stderr, "ends with unknown\n");
4275 //pc->print(stderr,pc);
4279 //fprintf(stderr, "ends with nothing: ERROR\n");
4283 /*-----------------------------------------------------------------*/
4284 /*-----------------------------------------------------------------*/
4286 /*-----------------------------------------------------------------*/
4287 /*-----------------------------------------------------------------*/
4288 int isPCinFlow(pCode *pc, pCode *pcflow)
4294 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4297 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4303 /*-----------------------------------------------------------------*/
4304 /*-----------------------------------------------------------------*/
4306 static void BanksUsedFlow2(pCode *pcflow)
4315 if(!isPCFL(pcflow)) {
4316 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4320 pc = findNextInstruction(pcflow->next);
4322 PCFL(pcflow)->lastBank = -1;
4324 while(isPCinFlow(pc,pcflow)) {
4326 int bank_selected = isBankInstruction(pc);
4328 //if(PCI(pc)->pcflow)
4329 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4331 if(bank_selected > 0) {
4332 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4334 // This instruction is modifying banking bits before accessing registers
4336 PCFL(pcflow)->firstBank = -1;
4338 if(PCFL(pcflow)->lastBank == -1)
4339 PCFL(pcflow)->lastBank = 0;
4341 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4342 if(bank_selected & SET_BANK_BIT)
4343 PCFL(pcflow)->lastBank |= bank;
4347 reg = getRegFromInstruction(pc);
4349 if(reg && !isREGinBank(reg, bank)) {
4350 int allbanks = REGallBanks(reg);
4352 PCFL(pcflow)->firstBank = allbanks;
4354 PCFL(pcflow)->lastBank = allbanks;
4361 pc = findNextInstruction(pc->next);
4364 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4365 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4368 /*-----------------------------------------------------------------*/
4369 /*-----------------------------------------------------------------*/
4371 static void BanksUsedFlow(pBlock *pb)
4376 //pb->pcHead->print(stderr, pb->pcHead);
4378 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4379 //pcflow->print(stderr,pcflow);
4381 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4383 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4385 BanksUsedFlow2(pcflow);
4391 /*-----------------------------------------------------------------*/
4392 /* Inserts a new pCodeInstruction before an existing one */
4393 /*-----------------------------------------------------------------*/
4394 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4397 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4399 /* Move the label, if there is one */
4402 new_pci->label = pci->label;
4406 /* Move the C code comment, if there is one */
4409 new_pci->cline = pci->cline;
4413 /* The new instruction has the same pcflow block */
4414 new_pci->pcflow = pci->pcflow;
4418 /*-----------------------------------------------------------------*/
4419 /*-----------------------------------------------------------------*/
4420 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4424 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4426 insertPCodeInstruction(pci, PCI(new_pc));
4429 /*-----------------------------------------------------------------*/
4430 /*-----------------------------------------------------------------*/
4431 static void insertBankSel(pCodeInstruction *pci, const char *name)
4435 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4436 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4437 if (pcop->name == 0)
4438 pcop->name = strdup(name);
4439 new_pc = newpCode(POC_BANKSEL, pcop);
4441 insertPCodeInstruction(pci, PCI(new_pc));
4444 /*-----------------------------------------------------------------*/
4445 /* If the register is a fixed known addess then we can assign the */
4446 /* bank selection bits. Otherwise the linker is going to assign */
4447 /* the register location and thus has to set bank selection bits */
4448 /* through the banksel directive. */
4449 /* One critical assumption here is that within this C module all */
4450 /* the locally allocated registers are in the same udata sector. */
4451 /* Therefore banksel is only called for external registers or the */
4452 /* first time a local register is encountered. */
4453 /*-----------------------------------------------------------------*/
4454 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4455 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4458 int a = reg->alias>>7;
4460 return cur_bank; // This register is available in all banks
4461 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4462 return cur_bank; // This register is available in banks 0 & 1
4464 if (reg->address&0x80) {
4465 if ((cur_bank==1)||(cur_bank==3)) {
4466 return cur_bank; // This register is available in banks 1 & 3
4469 if ((cur_bank==0)||(cur_bank==1)) {
4470 return cur_bank; // This register is available in banks 0 & 2
4475 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4477 LastRegIdx = reg->rIdx;
4480 bank = REG_BANK(reg);
4481 } else if (reg->isExtern) {
4482 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4484 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4486 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.
4487 return 'L'; // Local registers are presumed to be in same linker assigned bank
4488 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4489 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4490 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4491 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4492 } 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
4493 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4494 if (getMaxRam()&0x100)
4495 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4496 } else { // Current bank and new register banks known - can set bank bits
4497 switch((cur_bank^bank) & 3) {
4501 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4504 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4507 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4508 if (getMaxRam()&0x100)
4509 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4517 /*-----------------------------------------------------------------*/
4518 /* Check for bank selection pcodes instructions and modify */
4519 /* cur_bank to match. */
4520 /*-----------------------------------------------------------------*/
4521 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4523 if (isSTATUS_REG(reg)) {
4525 if (PCI(pc)->op == POC_BCF) {
4526 int old_bank = *cur_bank;
4527 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4528 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4529 if (*cur_bank & ~(0x3))
4532 *cur_bank = *cur_bank&0x2;
4533 LastRegIdx = reg->rIdx;
4534 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4535 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4536 if (*cur_bank & ~(0x3))
4539 *cur_bank = *cur_bank&0x1;
4540 LastRegIdx = reg->rIdx;
4542 return old_bank != *cur_bank;
4545 if (PCI(pc)->op == POC_BSF) {
4546 int old_bank = *cur_bank;
4547 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4548 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4549 if (*cur_bank & ~(0x3))
4552 *cur_bank = (*cur_bank&0x2) | 0x1;
4553 LastRegIdx = reg->rIdx;
4554 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4555 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4556 if (*cur_bank & ~(0x3))
4559 *cur_bank = (*cur_bank&0x1) | 0x2;
4560 LastRegIdx = reg->rIdx;
4562 return old_bank != *cur_bank;
4565 } else if (PCI(pc)->op == POC_BANKSEL) {
4566 int old_bank = *cur_bank;
4567 regs *r = PCOR(PCI(pc)->pcop)->r;
4568 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4569 LastRegIdx = reg->rIdx;
4570 return old_bank != *cur_bank;
4576 /*-----------------------------------------------------------------*/
4577 /* Set bank selection if necessary */
4578 /*-----------------------------------------------------------------*/
4579 static int DoBankSelect(pCode *pc, int cur_bank) {
4587 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4588 if (pcf && isPCF(pcf)) {
4590 int rbank = 'U'; // Undetermined
4591 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4592 // Check all the returns to work out what bank is selected
4593 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4595 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4597 rbank = PCFL(pcfr)->lastBank;
4599 if (rbank != PCFL(pcfr)->lastBank)
4600 return -1; // Unknown bank - multiple returns with different banks
4605 return -1; // Unknown bank
4607 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4608 /* Extern functions may use registers in different bank - must call banksel */
4609 return -1; /* Unknown bank */
4613 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4614 return -1; /* New bank unknown - linkers choice. */
4617 reg = getRegFromInstruction(pc);
4619 if (IsBankChange(pc,reg,&cur_bank))
4621 if (!isPCI_LIT(pc)) {
4623 /* Examine the instruction before this one to make sure it is
4624 * not a skip type instruction */
4625 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4627 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4628 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4630 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4632 if (!PCI(pc)->pcflow)
4633 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4635 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4641 /*-----------------------------------------------------------------*/
4642 /*-----------------------------------------------------------------*/
4644 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4652 pc = findNextInstruction(pcfl->pc.next);
4654 while(isPCinFlow(pc,PCODE(pcfl))) {
4656 cur_bank = DoBankSelect(pc,cur_bank);
4658 pc = findNextInstruction(pc->next);
4662 if(pcprev && cur_bank) {
4663 // Set bank state to unknown at the end of each flow block
4669 /*-----------------------------------------------------------------*/
4670 /*int compareBankFlow - compare the banking requirements between */
4672 /*-----------------------------------------------------------------*/
4674 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4677 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4680 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4683 if(pcflow->firstBank == -1)
4687 if(pcflowLink->pcflow->firstBank == -1) {
4688 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4689 pcflowLink->pcflow->to :
4690 pcflowLink->pcflow->from);
4691 return compareBankFlow(pcflow, pctl, toORfrom);
4695 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4698 pcflowLink->bank_conflict++;
4699 pcflowLink->pcflow->FromConflicts++;
4700 pcflow->ToConflicts++;
4703 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4706 pcflowLink->bank_conflict++;
4707 pcflowLink->pcflow->ToConflicts++;
4708 pcflow->FromConflicts++;
4712 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4713 pcflowLink->pcflow->pc.seq,
4714 pcflowLink->pcflow->FromConflicts,
4715 pcflowLink->pcflow->ToConflicts);
4721 /*-----------------------------------------------------------------*/
4722 /*-----------------------------------------------------------------*/
4724 void FixBankFlow(pBlock *pb)
4728 pCodeFlowLink *pcfl;
4730 pCode *pcflow_max_To=NULL;
4731 pCode *pcflow_max_From=NULL;
4732 int max_ToConflicts=0;
4733 int max_FromConflicts=0;
4735 /fprintf(stderr,"Fix Bank flow \n");
4736 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4740 First loop through all of the flow objects in this pcode block
4741 and fix the ones that have banking conflicts between the
4745 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4747 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4749 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4751 if(!isPCFL(pcflow)) {
4752 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4756 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4757 PCFL(pcflow)->firstBank >= 0 &&
4758 PCFL(pcflow)->lastBank >= 0 ) {
4760 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4761 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4763 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4764 BanksUsedFlow2(pcflow);
4769 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4771 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4773 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4778 if(!isPCFL(pcflow)) {
4779 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4783 PCFL(pcflow)->FromConflicts = 0;
4784 PCFL(pcflow)->ToConflicts = 0;
4789 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4790 pcfl = setFirstItem(PCFL(pcflow)->from);
4793 pc = PCODE(pcfl->pcflow);
4796 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4797 pc->print(stderr,pc);
4800 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4803 pcfl=setNextItem(PCFL(pcflow)->from);
4806 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4807 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4809 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4810 BanksUsedFlow2(pcflow);
4812 continue; / * Don't need to check the flow from here - it's already been fixed * /
4819 pcfl = setFirstItem(PCFL(pcflow)->to);
4822 pc = PCODE(pcfl->pcflow);
4824 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4825 pc->print(stderr,pc);
4828 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4831 pcfl=setNextItem(PCFL(pcflow)->to);
4834 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4835 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4837 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4838 BanksUsedFlow2(pcflow);
4843 Loop through the flow objects again and find the ones with the
4847 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4849 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4851 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4852 pcflow_max_To = pcflow;
4854 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4855 pcflow_max_From = pcflow;
4859 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4860 PCFL(pcflow_max_To)->pc.seq,
4861 PCFL(pcflow_max_To)->ToConflicts);
4864 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4865 PCFL(pcflow_max_From)->pc.seq,
4866 PCFL(pcflow_max_From)->FromConflicts);
4871 /*-----------------------------------------------------------------*/
4872 /*-----------------------------------------------------------------*/
4873 void DumpFlow(pBlock *pb)
4877 pCodeFlowLink *pcfl;
4880 fprintf(stderr,"Dump flow \n");
4881 pb->pcHead->print(stderr, pb->pcHead);
4883 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4884 pcflow->print(stderr,pcflow);
4886 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4888 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4890 if(!isPCFL(pcflow)) {
4891 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4894 fprintf(stderr,"dumping: ");
4895 pcflow->print(stderr,pcflow);
4896 FlowStats(PCFL(pcflow));
4898 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4900 pc = PCODE(pcfl->pcflow);
4902 fprintf(stderr, " from seq %d:\n",pc->seq);
4904 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4905 pc->print(stderr,pc);
4910 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4912 pc = PCODE(pcfl->pcflow);
4914 fprintf(stderr, " to seq %d:\n",pc->seq);
4916 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4917 pc->print(stderr,pc);
4926 /*-----------------------------------------------------------------*/
4927 /*-----------------------------------------------------------------*/
4928 int OptimizepBlock(pBlock *pb)
4933 if(!pb || !peepOptimizing)
4936 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4938 for(pc = pb->pcHead; pc; pc = pc->next)
4939 matches += pCodePeepMatchRule(pc);
4942 pc = findNextInstruction(pb->pcHead);
4950 if(pCodePeepMatchRule(pc)) {
4955 pc = findNextInstruction(pcprev->next);
4957 pc = findNextInstruction(pb->pcHead);
4959 pc = findNextInstruction(pc->next);
4963 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4968 /*-----------------------------------------------------------------*/
4969 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4970 /*-----------------------------------------------------------------*/
4971 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4975 for(pc = pcs; pc; pc = pc->next) {
4977 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4979 (PCI(pc)->pcop->type == PO_LABEL) &&
4980 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4987 /*-----------------------------------------------------------------*/
4988 /*-----------------------------------------------------------------*/
4989 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4996 (PCI(pc)->pcop->type == PO_LABEL)) {
4998 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5000 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5002 free(pcol->pcop.name);
5004 /* If the key is negative, then we (probably) have a label to
5005 * a function and the name is already defined */
5008 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5012 //sprintf(buffer,"_%05d_DS_",pcl->key);
5014 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5016 pcol->pcop.name = Safe_strdup(s);
5017 pcol->key = pcl->key;
5018 //pc->print(stderr,pc);
5025 /*-----------------------------------------------------------------*/
5026 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5027 /* pCode chain if they're not used. */
5028 /*-----------------------------------------------------------------*/
5029 void pBlockRemoveUnusedLabels(pBlock *pb)
5031 pCode *pc; pCodeLabel *pcl;
5036 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5038 pBranch *pbr = PCI(pc)->label;
5039 if(pbr && pbr->next) {
5040 pCode *pcd = pb->pcHead;
5042 //fprintf(stderr, "multiple labels\n");
5043 //pc->print(stderr,pc);
5048 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5049 //fprintf(stderr,"Used by:\n");
5050 //pcd->print(stderr,pcd);
5052 exchangeLabels(PCL(pbr->pc),pcd);
5061 for(pc = pb->pcHead; pc; pc = pc->next) {
5063 if(isPCL(pc)) // Label pcode
5065 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5066 pcl = PCL(PCI(pc)->label->pc);
5069 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5071 /* This pCode is a label, so search the pBlock to see if anyone
5074 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5075 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5076 /* Couldn't find an instruction that refers to this label
5077 * So, unlink the pCode label from it's pCode chain
5078 * and destroy the label */
5079 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5081 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5082 if(pc->type == PC_LABEL) {
5084 pCodeLabelDestruct(pc);
5086 unlinkpCodeFromBranch(pc, PCODE(pcl));
5087 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5098 /*-----------------------------------------------------------------*/
5099 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5100 /* chain and put them into pBranches that are */
5101 /* associated with the appropriate pCode */
5103 /*-----------------------------------------------------------------*/
5104 void pBlockMergeLabels(pBlock *pb)
5107 pCode *pc, *pcnext=NULL;
5112 /* First, Try to remove any unused labels */
5113 //pBlockRemoveUnusedLabels(pb);
5115 /* Now loop through the pBlock and merge the labels with the opcodes */
5118 // for(pc = pb->pcHead; pc; pc = pc->next) {
5121 pCode *pcn = pc->next;
5123 if(pc->type == PC_LABEL) {
5125 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5126 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5127 if((pcnext = findNextInstruction(pc) )) {
5129 // Unlink the pCode label from it's pCode chain
5132 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5133 // And link it into the instruction's pBranch labels. (Note, since
5134 // it's possible to have multiple labels associated with one instruction
5135 // we must provide a means to accomodate the additional labels. Thus
5136 // the labels are placed into the singly-linked list "label" as
5137 // opposed to being a single member of the pCodeInstruction.)
5139 //_ALLOC(pbr,sizeof(pBranch));
5140 pbr = Safe_calloc(1,sizeof(pBranch));
5144 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5147 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5149 } else if(pc->type == PC_CSOURCE) {
5151 /* merge the source line symbolic info into the next instruction */
5152 if((pcnext = findNextInstruction(pc) )) {
5154 // Unlink the pCode label from it's pCode chain
5156 PCI(pcnext)->cline = PCCS(pc);
5157 //fprintf(stderr, "merging CSRC\n");
5158 //genericPrint(stderr,pcnext);
5164 pBlockRemoveUnusedLabels(pb);
5168 /*-----------------------------------------------------------------*/
5169 /*-----------------------------------------------------------------*/
5170 int OptimizepCode(char dbName)
5172 #define MAX_PASSES 4
5181 DFPRINTF((stderr," Optimizing pCode\n"));
5185 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5186 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5187 matches += OptimizepBlock(pb);
5190 while(matches && ++passes < MAX_PASSES);
5195 /*-----------------------------------------------------------------*/
5196 /* popCopyGPR2Bit - copy a pcode operator */
5197 /*-----------------------------------------------------------------*/
5199 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5203 pcop = newpCodeOpBit(pc->name, bitval, 0);
5205 if( !( (pcop->type == PO_LABEL) ||
5206 (pcop->type == PO_LITERAL) ||
5207 (pcop->type == PO_STR) ))
5208 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5214 /*-----------------------------------------------------------------*/
5215 /*-----------------------------------------------------------------*/
5216 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5219 int firstBank = 'U';
5224 for (pc=pb->pcHead; pc; pc=pc->next) {
5226 firstBank = PCFL(pc)->firstBank;
5230 if (firstBank != 'U') {
5231 /* This block has already been done */
5232 if (firstBank != cur_bank) {
5233 /* This block has started with a different bank - must adjust it */
5234 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5237 regs *reg = getRegFromInstruction(pc);
5239 DoBankSelect(pc,cur_bank);
5249 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5252 for (pc=pb->pcHead; pc; pc=pc->next) {
5254 PCFL(pc)->firstBank = cur_bank;
5257 cur_bank = DoBankSelect(pc,cur_bank);
5260 /* Trace through branches and set the bank selection as required. */
5263 for (pc=pb->pcHead; pc; pc=pc->next) {
5265 PCFL(pc)->firstBank = cur_bank;
5269 if (PCI(pc)->op == POC_GOTO) {
5270 int lastRegIdx = LastRegIdx;
5272 /* Trace through branch */
5273 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5276 regs *reg = getRegFromInstruction(pcl);
5278 int bankUnknown = -1;
5279 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5281 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5287 LastRegIdx = lastRegIdx;
5289 /* Keep track out current bank */
5290 regs *reg = getRegFromInstruction(pc);
5292 IsBankChange(pc,reg,&cur_bank);
5299 /*-----------------------------------------------------------------*/
5300 /*-----------------------------------------------------------------*/
5301 void pBlockDestruct(pBlock *pb)
5312 /*-----------------------------------------------------------------*/
5313 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5314 /* name dbName and combine them */
5315 /* into one block */
5316 /*-----------------------------------------------------------------*/
5317 void mergepBlocks(char dbName)
5320 pBlock *pb, *pbmerged = NULL,*pbn;
5322 pb = the_pFile->pbHead;
5324 //fprintf(stderr," merging blocks named %c\n",dbName);
5328 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5329 if( getpBlock_dbName(pb) == dbName) {
5331 //fprintf(stderr," merged block %c\n",dbName);
5336 addpCode2pBlock(pbmerged, pb->pcHead);
5337 /* addpCode2pBlock doesn't handle the tail: */
5338 pbmerged->pcTail = pb->pcTail;
5340 pb->prev->next = pbn;
5342 pbn->prev = pb->prev;
5347 //printpBlock(stderr, pbmerged);
5354 /*-----------------------------------------------------------------*/
5355 /* AnalyzeFlow - Examine the flow of the code and optimize */
5357 /* level 0 == minimal optimization */
5358 /* optimize registers that are used only by two instructions */
5359 /* level 1 == maximal optimization */
5360 /* optimize by looking at pairs of instructions that use the */
5362 /*-----------------------------------------------------------------*/
5364 void AnalyzeFlow(int level)
5366 static int times_called=0;
5374 /* if this is not the first time this function has been called,
5375 then clean up old flow information */
5376 if(times_called++) {
5377 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5380 RegsUnMapLiveRanges();
5386 /* Phase 2 - Flow Analysis - Register Banking
5388 * In this phase, the individual flow blocks are examined
5389 * and register banking is fixed.
5392 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5393 //FixRegisterBanking(pb);
5395 /* Phase 2 - Flow Analysis
5397 * In this phase, the pCode is partition into pCodeFlow
5398 * blocks. The flow blocks mark the points where a continuous
5399 * stream of instructions changes flow (e.g. because of
5400 * a call or goto or whatever).
5403 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5407 /* Phase 2 - Flow Analysis - linking flow blocks
5409 * In this phase, the individual flow blocks are examined
5410 * to determine their order of excution.
5413 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5416 /* Phase 3 - Flow Analysis - Flow Tree
5418 * In this phase, the individual flow blocks are examined
5419 * to determine their order of excution.
5422 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5426 /* Phase x - Flow Analysis - Used Banks
5428 * In this phase, the individual flow blocks are examined
5429 * to determine the Register Banks they use
5432 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5436 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5437 pCodeRegMapLiveRanges(pb);
5439 RemoveUnusedRegisters();
5441 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5442 pCodeRegOptimizeRegUsage(level);
5448 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5453 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5455 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5456 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5457 pcflow = pcflow->next) {
5459 FillFlow(PCFL(pcflow));
5464 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5466 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5467 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5468 pcflow = pcflow->next) {
5470 FlowStats(PCFL(pcflow));
5476 /*-----------------------------------------------------------------*/
5477 /* AnalyzeBanking - Called after the memory addresses have been */
5478 /* assigned to the registers. */
5480 /*-----------------------------------------------------------------*/
5482 void AnalyzeBanking(void)
5486 if(!picIsInitialized()) {
5487 setDefMaxRam(); // Max RAM has not been included, so use default setting
5490 /* Phase x - Flow Analysis - Used Banks
5492 * In this phase, the individual flow blocks are examined
5493 * to determine the Register Banks they use
5499 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5500 // BanksUsedFlow(pb);
5501 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5502 FixRegisterBanking(pb,-1); // cur_bank is unknown
5506 /*-----------------------------------------------------------------*/
5507 /*-----------------------------------------------------------------*/
5508 DEFSETFUNC (resetrIdx)
5510 regs *r = (regs *)item;
5518 /*-----------------------------------------------------------------*/
5519 /* InitRegReuse - Initialises variables for code analyzer */
5520 /*-----------------------------------------------------------------*/
5522 void InitReuseReg(void)
5524 /* Find end of statically allocated variables for start idx */
5525 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5527 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5528 if (r->type != REG_SFR) {
5529 maxIdx += r->size; /* Increment for all statically allocated variables */
5533 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5536 /*-----------------------------------------------------------------*/
5537 /*-----------------------------------------------------------------*/
5538 static unsigned register_reassign(pBlock *pb, unsigned idx)
5542 /* check recursion */
5543 pc = setFirstItem(pb->function_entries);
5549 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5551 if (pb->tregisters) {
5553 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5554 if (r->type == REG_GPR) {
5556 if (r->rIdx < (int)idx) {
5559 if (peakIdx < idx) peakIdx = idx;
5560 sprintf(s,"r0x%02X", r->rIdx);
5561 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5563 r->name = Safe_strdup(s);
5569 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5571 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5572 char *dest = get_op_from_instruction(PCI(pc));
5574 pCode *pcn = findFunction(dest);
5576 register_reassign(pcn->pb,idx);
5585 /*------------------------------------------------------------------*/
5586 /* ReuseReg were call tree permits */
5588 /* Re-allocate the GPR for optimum reuse for a given pblock */
5589 /* eg if a function m() calls function f1() and f2(), where f1 */
5590 /* allocates a local variable vf1 and f2 allocates a local */
5591 /* variable vf2. Then providing f1 and f2 do not call each other */
5592 /* they may share the same general purpose registers for vf1 and */
5594 /* This is done by first setting the the regs rIdx to start after */
5595 /* all the global variables, then walking through the call tree */
5596 /* renaming the registers to match their new idx and incrementng */
5597 /* it as it goes. If a function has already been called it will */
5598 /* only rename the registers if it has already used up those */
5599 /* registers ie rIdx of the function's registers is lower than the */
5600 /* current rIdx. That way the register will not be reused while */
5601 /* still being used by an eariler function call. */
5603 /* Note for this to work the functions need to be declared static. */
5605 /*------------------------------------------------------------------*/
5610 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5611 /* Non static functions can be called from other modules so their registers must reassign */
5612 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5613 register_reassign(pb,peakIdx);
5617 /*-----------------------------------------------------------------*/
5618 /* buildCallTree - look at the flow and extract all of the calls */
5620 /*-----------------------------------------------------------------*/
5622 void buildCallTree(void )
5631 /* Now build the call tree.
5632 First we examine all of the pCodes for functions.
5633 Keep in mind that the function boundaries coincide
5634 with pBlock boundaries.
5636 The algorithm goes something like this:
5637 We have two nested loops. The outer loop iterates
5638 through all of the pBlocks/functions. The inner
5639 loop iterates through all of the pCodes for
5640 a given pBlock. When we begin iterating through
5641 a pBlock, the variable pc_fstart, pCode of the start
5642 of a function, is cleared. We then search for pCodes
5643 of type PC_FUNCTION. When one is encountered, we
5644 initialize pc_fstart to this and at the same time
5645 associate a new pBranch object that signifies a
5646 branch entry. If a return is found, then this signifies
5647 a function exit point. We'll link the pCodes of these
5648 returns to the matching pc_fstart.
5650 When we're done, a doubly linked list of pBranches
5651 will exist. The head of this list is stored in
5652 `the_pFile', which is the meta structure for all
5653 of the pCode. Look at the printCallTree function
5654 on how the pBranches are linked together.
5657 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5658 pCode *pc_fstart=NULL;
5659 for(pc = pb->pcHead; pc; pc = pc->next) {
5661 pCodeFunction *pcf = PCF(pc);
5664 if(STRCASECMP(pcf->fname, "_main") == 0) {
5665 //fprintf(stderr," found main \n");
5666 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5670 pbr = Safe_calloc(1,sizeof(pBranch));
5671 pbr->pc = pc_fstart = pc;
5674 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5676 // Here's a better way of doing the same:
5677 addSet(&pb->function_entries, pc);
5680 // Found an exit point in a function, e.g. return
5681 // (Note, there may be more than one return per function)
5683 pBranchLink(PCF(pc_fstart), pcf);
5685 addSet(&pb->function_exits, pc);
5687 } else if(isCALL(pc)) {
5688 addSet(&pb->function_calls,pc);
5694 /*-----------------------------------------------------------------*/
5695 /* AnalyzepCode - parse the pCode that has been generated and form */
5696 /* all of the logical connections. */
5698 /* Essentially what's done here is that the pCode flow is */
5700 /*-----------------------------------------------------------------*/
5702 void AnalyzepCode(char dbName)
5713 /* Phase 1 - Register allocation and peep hole optimization
5715 * The first part of the analysis is to determine the registers
5716 * that are used in the pCode. Once that is done, the peep rules
5717 * are applied to the code. We continue to loop until no more
5718 * peep rule optimizations are found (or until we exceed the
5719 * MAX_PASSES threshold).
5721 * When done, the required registers will be determined.
5727 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5729 /* First, merge the labels with the instructions */
5730 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5731 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5733 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5734 pBlockMergeLabels(pb);
5737 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5741 changes = OptimizepCode(dbName);
5743 } while(changes && (i++ < MAX_PASSES));
5748 /*-----------------------------------------------------------------*/
5749 /* ispCodeFunction - returns true if *pc is the pCode of a */
5751 /*-----------------------------------------------------------------*/
5752 bool ispCodeFunction(pCode *pc)
5755 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5761 /*-----------------------------------------------------------------*/
5762 /* findFunction - Search for a function by name (given the name) */
5763 /* in the set of all functions that are in a pBlock */
5764 /* (note - I expect this to change because I'm planning to limit */
5765 /* pBlock's to just one function declaration */
5766 /*-----------------------------------------------------------------*/
5767 pCode *findFunction(char *fname)
5774 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5776 pc = setFirstItem(pb->function_entries);
5779 if((pc->type == PC_FUNCTION) &&
5781 (strcmp(fname, PCF(pc)->fname)==0))
5784 pc = setNextItem(pb->function_entries);
5792 void MarkUsedRegisters(set *regset)
5797 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5798 r2 = pic14_regWithIdx(r1->rIdx);
5806 void pBlockStats(FILE *of, pBlock *pb)
5812 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5814 // for now just print the first element of each set
5815 pc = setFirstItem(pb->function_entries);
5817 fprintf(of,";entry: ");
5820 pc = setFirstItem(pb->function_exits);
5822 fprintf(of,";has an exit\n");
5826 pc = setFirstItem(pb->function_calls);
5828 fprintf(of,";functions called:\n");
5831 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5832 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5834 pc = setNextItem(pb->function_calls);
5838 r = setFirstItem(pb->tregisters);
5840 int n = elementsInSet(pb->tregisters);
5842 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5845 fprintf(of,"; %s\n",r->name);
5846 r = setNextItem(pb->tregisters);
5851 /*-----------------------------------------------------------------*/
5852 /*-----------------------------------------------------------------*/
5854 static void sequencepCode(void)
5860 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5862 pb->seq = GpCodeSequenceNumber+1;
5864 for( pc = pb->pcHead; pc; pc = pc->next)
5865 pc->seq = ++GpCodeSequenceNumber;
5871 /*-----------------------------------------------------------------*/
5872 /*-----------------------------------------------------------------*/
5874 set *register_usage(pBlock *pb)
5877 set *registers=NULL;
5878 set *registersInCallPath = NULL;
5880 / * check recursion * /
5882 pc = setFirstItem(pb->function_entries);
5889 if(pc->type != PC_FUNCTION)
5890 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5892 pc = setFirstItem(pb->function_calls);
5893 for( ; pc; pc = setNextItem(pb->function_calls)) {
5895 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5896 char *dest = get_op_from_instruction(PCI(pc));
5898 pcn = findFunction(dest);
5900 registersInCallPath = register_usage(pcn->pb);
5902 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5907 pBlockStats(stderr,pb); // debug
5910 // Mark the registers in this block as used.
5912 MarkUsedRegisters(pb->tregisters);
5913 if(registersInCallPath) {
5914 / * registers were used in the functions this pBlock has called * /
5915 / * so now, we need to see if these collide with the ones we are * /
5918 regs *r1,*r2, *newreg;
5920 DFPRINTF((stderr,"comparing registers\n"));
5922 r1 = setFirstItem(registersInCallPath);
5924 if (r1->type != REG_STK) {
5925 r2 = setFirstItem(pb->tregisters);
5927 while(r2 && (r2->type != REG_STK)) {
5929 if(r2->rIdx == r1->rIdx) {
5930 newreg = pic14_findFreeReg(REG_GPR);
5934 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5938 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5939 r1->rIdx, newreg->rIdx));
5940 r2->rIdx = newreg->rIdx;
5942 r2->name = Safe_strdup(newreg->name);
5946 newreg->wasUsed = 1;
5948 r2 = setNextItem(pb->tregisters);
5952 r1 = setNextItem(registersInCallPath);
5955 / * Collisions have been resolved. Now free the registers in the call path * /
5956 r1 = setFirstItem(registersInCallPath);
5958 newreg = pic14_regWithIdx(r1->rIdx);
5959 if (newreg) newreg->isFree = 1;
5960 r1 = setNextItem(registersInCallPath);
5964 // MarkUsedRegisters(pb->registers);
5966 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5969 DFPRINTF((stderr,"returning regs\n"));
5971 DFPRINTF((stderr,"not returning regs\n"));
5973 DFPRINTF((stderr,"pBlock after register optim.\n"));
5974 pBlockStats(stderr,pb); // debug
5981 /*-----------------------------------------------------------------*/
5982 /* printCallTree - writes the call tree to a file */
5984 /*-----------------------------------------------------------------*/
5985 void pct2(FILE *of,pBlock *pb,int indent)
5989 // set *registersInCallPath = NULL;
5995 return; //recursion ?
5997 pc = setFirstItem(pb->function_entries);
6004 for(i=0;i<indent;i++) // Indentation
6007 if(pc->type == PC_FUNCTION)
6008 fprintf(of,"%s\n",PCF(pc)->fname);
6013 pc = setFirstItem(pb->function_calls);
6014 for( ; pc; pc = setNextItem(pb->function_calls)) {
6016 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6017 char *dest = get_op_from_instruction(PCI(pc));
6019 pcn = findFunction(dest);
6021 pct2(of,pcn->pb,indent+1);
6023 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6031 /*-----------------------------------------------------------------*/
6032 /* printCallTree - writes the call tree to a file */
6034 /*-----------------------------------------------------------------*/
6036 void printCallTree(FILE *of)
6048 fprintf(of, "\npBlock statistics\n");
6049 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6054 fprintf(of,"Call Tree\n");
6055 pbr = the_pFile->functions;
6059 if(!ispCodeFunction(pc))
6060 fprintf(of,"bug in call tree");
6063 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6065 while(pc->next && !ispCodeFunction(pc->next)) {
6067 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6068 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6076 fprintf(of,"\n**************\n\na better call tree\n");
6077 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6082 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6083 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6089 /*-----------------------------------------------------------------*/
6091 /*-----------------------------------------------------------------*/
6093 void InlineFunction(pBlock *pb)
6101 pc = setFirstItem(pb->function_calls);
6103 for( ; pc; pc = setNextItem(pb->function_calls)) {
6106 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6107 pCode *pcp = pc->prev;
6113 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 */
6115 InlineFunction(pcn->pb);
6118 At this point, *pc points to a CALL mnemonic, and
6119 *pcn points to the function that is being called.
6121 To in-line this call, we need to remove the CALL
6122 and RETURN(s), and link the function pCode in with
6129 /* Check if previous instruction was a bit skip */
6130 if (isPCI_BITSKIP(pcp)) {
6132 /* Invert skip instruction and add a goto */
6133 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6135 if(isPCL(pc_call->next)) { // Label pcode
6136 pcl = PCL(pc_call->next);
6137 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6138 pcl = PCL(PCI(pc_call->next)->label->pc);
6140 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6141 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6143 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6146 /* remove callee pBlock from the pBlock linked list */
6147 removepBlock(pcn->pb);
6155 /* Remove the Function pCode */
6156 pct = findNextInstruction(pcn->next);
6158 /* Link the function with the callee */
6159 if (pcp) pcp->next = pcn->next;
6160 pcn->next->prev = pcp;
6162 /* Convert the function name into a label */
6164 pbr = Safe_calloc(1,sizeof(pBranch));
6165 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6167 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6168 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6170 /* turn all of the return's except the last into goto's */
6171 /* check case for 2 instruction pBlocks */
6172 pce = findNextInstruction(pcn->next);
6174 pCode *pce_next = findNextInstruction(pce->next);
6176 if(pce_next == NULL) {
6177 /* found the last return */
6178 pCode *pc_call_next = findNextInstruction(pc_call->next);
6180 //fprintf(stderr,"found last return\n");
6181 //pce->print(stderr,pce);
6182 pce->prev->next = pc_call->next;
6183 pc_call->next->prev = pce->prev;
6184 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6193 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6199 /*-----------------------------------------------------------------*/
6201 /*-----------------------------------------------------------------*/
6203 void InlinepCode(void)
6212 if(!functionInlining)
6215 /* Loop through all of the function definitions and count the
6216 * number of times each one is called */
6217 //fprintf(stderr,"inlining %d\n",__LINE__);
6219 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6221 pc = setFirstItem(pb->function_calls);
6223 for( ; pc; pc = setNextItem(pb->function_calls)) {
6226 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6227 if(pcn && isPCF(pcn)) {
6228 PCF(pcn)->ncalled++;
6231 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6236 //fprintf(stderr,"inlining %d\n",__LINE__);
6238 /* Now, Loop through the function definitions again, but this
6239 * time inline those functions that have only been called once. */
6241 InlineFunction(the_pFile->pbHead);
6242 //fprintf(stderr,"inlining %d\n",__LINE__);
6244 for(pb = the_pFile->pbHead; pb; pb = pb->next)