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 stkSize = 16; // Set pseudo stack size to 16
1349 initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters
1350 init_pic(port->processor);
1351 if ((unsigned)shareBankAddress > getMaxRam())
1352 shareBankAddress = (int)getMaxRam();
1354 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1355 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1356 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1357 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1358 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1359 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1361 pc_status.rIdx = IDX_STATUS;
1362 pc_fsr.rIdx = IDX_FSR;
1363 pc_indf.rIdx = IDX_INDF;
1364 pc_intcon.rIdx = IDX_INTCON;
1365 pc_pcl.rIdx = IDX_PCL;
1366 pc_pclath.rIdx = IDX_PCLATH;
1368 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. */
1369 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1370 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1372 pc_wsave.rIdx = pc_wsave.r->rIdx;
1373 pc_ssave.rIdx = pc_ssave.r->rIdx;
1374 pc_psave.rIdx = pc_psave.r->rIdx;
1376 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1377 pc_wsave.r->address = shareBankAddress-stkSize;
1378 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1379 pc_ssave.r->address = shareBankAddress-stkSize-1;
1380 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1381 pc_psave.r->address = shareBankAddress-stkSize-2;
1383 /* probably should put this in a separate initialization routine */
1384 pb_dead_pcodes = newpBlock();
1388 /*-----------------------------------------------------------------*/
1389 /* mnem2key - convert a pic mnemonic into a hash key */
1390 /* (BTW - this spreads the mnemonics quite well) */
1392 /*-----------------------------------------------------------------*/
1394 int mnem2key(char const *mnem)
1403 key += toupper(*mnem++) +1;
1407 return (key & 0x1f);
1411 void pic14initMnemonics(void)
1416 pCodeInstruction *pci;
1418 if(mnemonics_initialized)
1421 //FIXME - probably should NULL out the array before making the assignments
1422 //since we check the array contents below this initialization.
1424 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1425 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1426 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1427 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1428 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1429 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1430 pic14Mnemonics[POC_BCF] = &pciBCF;
1431 pic14Mnemonics[POC_BSF] = &pciBSF;
1432 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1433 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1434 pic14Mnemonics[POC_CALL] = &pciCALL;
1435 pic14Mnemonics[POC_COMF] = &pciCOMF;
1436 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1437 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1438 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1439 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1440 pic14Mnemonics[POC_DECF] = &pciDECF;
1441 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1442 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1443 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1444 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1445 pic14Mnemonics[POC_INCF] = &pciINCF;
1446 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1447 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1448 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1449 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1450 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1451 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1452 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1453 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1454 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1455 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1456 pic14Mnemonics[POC_NOP] = &pciNOP;
1457 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1458 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1459 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1460 pic14Mnemonics[POC_RLF] = &pciRLF;
1461 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1462 pic14Mnemonics[POC_RRF] = &pciRRF;
1463 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1464 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1465 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1466 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1467 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1468 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1469 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1470 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1471 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1472 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1473 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1474 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1476 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1477 if(pic14Mnemonics[i])
1478 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1479 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1482 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1483 pci = hTabNextItem(pic14MnemonicsHash, &key);
1486 mnemonics_initialized = 1;
1489 int getpCodePeepCommand(char *cmd);
1491 int getpCode(char *mnem,unsigned dest)
1494 pCodeInstruction *pci;
1495 int key = mnem2key(mnem);
1497 if(!mnemonics_initialized)
1498 pic14initMnemonics();
1500 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1504 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1505 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1509 pci = hTabNextItemWK (pic14MnemonicsHash);
1516 /*-----------------------------------------------------------------*
1517 * pic14initpCodePeepCommands
1519 *-----------------------------------------------------------------*/
1520 void pic14initpCodePeepCommands(void)
1528 hTabAddItem(&pic14pCodePeepCommandsHash,
1529 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1531 } while (peepCommands[i].cmd);
1533 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1536 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1537 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1542 /*-----------------------------------------------------------------
1545 *-----------------------------------------------------------------*/
1547 int getpCodePeepCommand(char *cmd)
1551 int key = mnem2key(cmd);
1554 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1557 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1558 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1562 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1569 char getpBlock_dbName(pBlock *pb)
1575 return pb->cmemmap->dbName;
1579 void pBlockConvert2ISR(pBlock *pb)
1590 /*-----------------------------------------------------------------*/
1591 /* movepBlock2Head - given the dbname of a pBlock, move all */
1592 /* instances to the front of the doubly linked */
1593 /* list of pBlocks */
1594 /*-----------------------------------------------------------------*/
1596 void movepBlock2Head(char dbName)
1603 pb = the_pFile->pbHead;
1607 if(getpBlock_dbName(pb) == dbName) {
1608 pBlock *pbn = pb->next;
1609 pb->next = the_pFile->pbHead;
1610 the_pFile->pbHead->prev = pb;
1611 the_pFile->pbHead = pb;
1614 pb->prev->next = pbn;
1616 // If the pBlock that we just moved was the last
1617 // one in the link of all of the pBlocks, then we
1618 // need to point the tail to the block just before
1619 // the one we moved.
1620 // Note: if pb->next is NULL, then pb must have
1621 // been the last pBlock in the chain.
1624 pbn->prev = pb->prev;
1626 the_pFile->pbTail = pb->prev;
1637 void copypCode(FILE *of, char dbName)
1641 if(!of || !the_pFile)
1644 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1645 if(getpBlock_dbName(pb) == dbName) {
1653 void pcode_test(void)
1656 DFPRINTF((stderr,"pcode is alive!\n"));
1666 /* create the file name */
1667 strcpy(buffer,dstFileName);
1668 strcat(buffer,".p");
1670 if( !(pFile = fopen(buffer, "w" ))) {
1671 werror(E_FILE_OPEN_ERR,buffer);
1675 fprintf(pFile,"pcode dump\n\n");
1677 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1678 fprintf(pFile,"\n\tNew pBlock\n\n");
1680 fprintf(pFile,"%s",pb->cmemmap->sname);
1682 fprintf(pFile,"internal pblock");
1684 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1685 printpBlock(pFile,pb);
1689 /*-----------------------------------------------------------------*/
1690 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1691 /* ister, RegCond will return the bit being referenced. */
1693 /* fixme - why not just OR in the pcop bit field */
1694 /*-----------------------------------------------------------------*/
1696 static int RegCond(pCodeOp *pcop)
1702 if (pcop->type == PO_GPR_BIT) {
1703 char *name = pcop->name;
1705 name = PCOR(pcop)->r->name;
1706 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1707 switch(PCORB(pcop)->bit) {
1721 /*-----------------------------------------------------------------*/
1722 /* newpCode - create and return a newly initialized pCode */
1724 /* fixme - rename this */
1726 /* The purpose of this routine is to create a new Instruction */
1727 /* pCode. This is called by gen.c while the assembly code is being */
1731 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1732 /* (note that the op is analogous to but not the */
1733 /* same thing as the opcode of the instruction.) */
1734 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1737 /* a pointer to the new malloc'd pCode is returned. */
1741 /*-----------------------------------------------------------------*/
1742 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1744 pCodeInstruction *pci ;
1746 if(!mnemonics_initialized)
1747 pic14initMnemonics();
1749 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1751 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1752 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1753 pci->pc.id = PCodeID();
1756 if(pci->inCond & PCC_EXAMINE_PCOP)
1757 pci->inCond |= RegCond(pcop);
1759 if(pci->outCond & PCC_EXAMINE_PCOP)
1760 pci->outCond |= RegCond(pcop);
1762 pci->pc.prev = pci->pc.next = NULL;
1763 return (pCode *)pci;
1766 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1772 /*-----------------------------------------------------------------*/
1773 /* newpCodeWild - create a "wild" as in wild card pCode */
1775 /* Wild pcodes are used during the peep hole optimizer to serve */
1776 /* as place holders for any instruction. When a snippet of code is */
1777 /* compared to a peep hole rule, the wild card opcode will match */
1778 /* any instruction. However, the optional operand and label are */
1779 /* additional qualifiers that must also be matched before the */
1780 /* line (of assembly code) is declared matched. Note that the */
1781 /* operand may be wild too. */
1783 /* Note, a wild instruction is specified just like a wild var: */
1784 /* %4 ; A wild instruction, */
1785 /* See the peeph.def file for additional examples */
1787 /*-----------------------------------------------------------------*/
1789 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1794 pcw = Safe_calloc(1,sizeof(pCodeWild));
1796 pcw->pci.pc.type = PC_WILD;
1797 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1798 pcw->id = PCodeID();
1799 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1800 pcw->pci.pc.pb = NULL;
1802 // pcw->pci.pc.analyze = genericAnalyze;
1803 pcw->pci.pc.destruct = genericDestruct;
1804 pcw->pci.pc.print = genericPrint;
1806 pcw->id = pCodeID; // this is the 'n' in %n
1807 pcw->operand = optional_operand;
1808 pcw->label = optional_label;
1810 pcw->mustBeBitSkipInst = 0;
1811 pcw->mustNotBeBitSkipInst = 0;
1812 pcw->invertBitSkipInst = 0;
1814 return ( (pCode *)pcw);
1818 /*-----------------------------------------------------------------*/
1819 /* newPcodeInlineP - create a new pCode from a char string */
1820 /*-----------------------------------------------------------------*/
1823 pCode *newpCodeInlineP(char *cP)
1828 pcc = Safe_calloc(1,sizeof(pCodeComment));
1830 pcc->pc.type = PC_INLINE;
1831 pcc->pc.prev = pcc->pc.next = NULL;
1832 pcc->pc.id = PCodeID();
1833 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1836 // pcc->pc.analyze = genericAnalyze;
1837 pcc->pc.destruct = genericDestruct;
1838 pcc->pc.print = genericPrint;
1841 pcc->comment = Safe_strdup(cP);
1843 pcc->comment = NULL;
1845 return ( (pCode *)pcc);
1849 /*-----------------------------------------------------------------*/
1850 /* newPcodeCharP - create a new pCode from a char string */
1851 /*-----------------------------------------------------------------*/
1853 pCode *newpCodeCharP(char *cP)
1858 pcc = Safe_calloc(1,sizeof(pCodeComment));
1860 pcc->pc.type = PC_COMMENT;
1861 pcc->pc.prev = pcc->pc.next = NULL;
1862 pcc->pc.id = PCodeID();
1863 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1866 // pcc->pc.analyze = genericAnalyze;
1867 pcc->pc.destruct = genericDestruct;
1868 pcc->pc.print = genericPrint;
1871 pcc->comment = Safe_strdup(cP);
1873 pcc->comment = NULL;
1875 return ( (pCode *)pcc);
1879 /*-----------------------------------------------------------------*/
1880 /* newpCodeFunction - */
1881 /*-----------------------------------------------------------------*/
1884 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1888 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1889 //_ALLOC(pcf,sizeof(pCodeFunction));
1891 pcf->pc.type = PC_FUNCTION;
1892 pcf->pc.prev = pcf->pc.next = NULL;
1893 pcf->pc.id = PCodeID();
1894 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1897 // pcf->pc.analyze = genericAnalyze;
1898 pcf->pc.destruct = genericDestruct;
1899 pcf->pc.print = pCodePrintFunction;
1904 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1905 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1906 strcpy(pcf->modname,mod);
1908 pcf->modname = NULL;
1911 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1912 pcf->fname = Safe_calloc(1,strlen(f)+1);
1913 strcpy(pcf->fname,f);
1917 pcf->isPublic = (unsigned)isPublic;
1919 return ( (pCode *)pcf);
1923 /*-----------------------------------------------------------------*/
1925 /*-----------------------------------------------------------------*/
1926 void destructpCodeFlow(pCode *pc)
1928 if(!pc || !isPCFL(pc))
1937 deleteSet(&PCFL(pc)->registers);
1938 deleteSet(&PCFL(pc)->from);
1939 deleteSet(&PCFL(pc)->to);
1944 pCode *newpCodeFlow(void )
1948 //_ALLOC(pcflow,sizeof(pCodeFlow));
1949 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1951 pcflow->pc.type = PC_FLOW;
1952 pcflow->pc.prev = pcflow->pc.next = NULL;
1953 pcflow->pc.pb = NULL;
1955 // pcflow->pc.analyze = genericAnalyze;
1956 pcflow->pc.destruct = destructpCodeFlow;
1957 pcflow->pc.print = genericPrint;
1959 pcflow->pc.seq = GpcFlowSeq++;
1961 pcflow->from = pcflow->to = NULL;
1963 pcflow->inCond = PCC_NONE;
1964 pcflow->outCond = PCC_NONE;
1966 pcflow->firstBank = 'U'; /* Undetermined */
1967 pcflow->lastBank = 'U'; /* Undetermined */
1969 pcflow->FromConflicts = 0;
1970 pcflow->ToConflicts = 0;
1974 pcflow->registers = newSet();
1976 return ( (pCode *)pcflow);
1980 /*-----------------------------------------------------------------*/
1981 /*-----------------------------------------------------------------*/
1982 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1984 pCodeFlowLink *pcflowLink;
1986 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1988 pcflowLink->pcflow = pcflow;
1989 pcflowLink->bank_conflict = 0;
1994 /*-----------------------------------------------------------------*/
1995 /* newpCodeCSource - create a new pCode Source Symbol */
1996 /*-----------------------------------------------------------------*/
1998 pCode *newpCodeCSource(int ln, char *f, char *l)
2003 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2005 pccs->pc.type = PC_CSOURCE;
2006 pccs->pc.prev = pccs->pc.next = NULL;
2007 pccs->pc.id = PCodeID();
2010 pccs->pc.destruct = genericDestruct;
2011 pccs->pc.print = genericPrint;
2013 pccs->line_number = ln;
2015 pccs->line = Safe_strdup(l);
2020 pccs->file_name = Safe_strdup(f);
2022 pccs->file_name = NULL;
2024 return ( (pCode *)pccs);
2028 /*******************************************************************/
2029 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2030 /* added by VR 6-Jun-2003 */
2031 /*******************************************************************/
2033 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2040 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2041 pcad->pci.pc.type = PC_ASMDIR;
2042 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2043 pcad->pci.pc.pb = NULL;
2044 pcad->pci.pc.destruct = genericDestruct;
2045 pcad->pci.pc.print = genericPrint;
2047 if(asdir && *asdir) {
2049 while(isspace(*asdir))asdir++; // strip any white space from the beginning
2051 pcad->directive = Safe_strdup( asdir );
2054 va_start(ap, argfmt);
2056 memset(buffer, 0, sizeof(buffer));
2057 if(argfmt && *argfmt)
2058 vsprintf(buffer, argfmt, ap);
2062 while(isspace(*lbp))lbp++;
2065 pcad->arg = Safe_strdup( lbp );
2067 return ((pCode *)pcad);
2070 /*-----------------------------------------------------------------*/
2071 /* pCodeLabelDestruct - free memory used by a label. */
2072 /*-----------------------------------------------------------------*/
2073 static void pCodeLabelDestruct(pCode *pc)
2079 if((pc->type == PC_LABEL) && PCL(pc)->label)
2080 free(PCL(pc)->label);
2086 pCode *newpCodeLabel(char *name, int key)
2092 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2094 pcl->pc.type = PC_LABEL;
2095 pcl->pc.prev = pcl->pc.next = NULL;
2096 pcl->pc.id = PCodeID();
2097 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2100 // pcl->pc.analyze = genericAnalyze;
2101 pcl->pc.destruct = pCodeLabelDestruct;
2102 pcl->pc.print = pCodePrintLabel;
2108 sprintf(s,"_%05d_DS_",key);
2113 pcl->label = Safe_strdup(s);
2115 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2116 return ( (pCode *)pcl);
2121 /*-----------------------------------------------------------------*/
2122 /* newpBlock - create and return a pointer to a new pBlock */
2123 /*-----------------------------------------------------------------*/
2124 pBlock *newpBlock(void)
2129 PpB = Safe_calloc(1,sizeof(pBlock) );
2130 PpB->next = PpB->prev = NULL;
2132 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2133 PpB->tregisters = NULL;
2135 PpB->FlowTree = NULL;
2141 /*-----------------------------------------------------------------*/
2142 /* newpCodeChain - create a new chain of pCodes */
2143 /*-----------------------------------------------------------------*
2145 * This function will create a new pBlock and the pointer to the
2146 * pCode that is passed in will be the first pCode in the block.
2147 *-----------------------------------------------------------------*/
2150 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2153 pBlock *pB = newpBlock();
2155 pB->pcHead = pB->pcTail = pc;
2162 /*-----------------------------------------------------------------*/
2163 /* newpCodeOpLabel - Create a new label given the key */
2164 /* Note, a negative key means that the label is part of wild card */
2165 /* (and hence a wild card label) used in the pCodePeep */
2166 /* optimizations). */
2167 /*-----------------------------------------------------------------*/
2169 pCodeOp *newpCodeOpLabel(char *name, int key)
2172 static int label_key=-1;
2176 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2177 pcop->type = PO_LABEL;
2182 sprintf(s=buffer,"_%05d_DS_",key);
2184 s = name, key = label_key--;
2186 PCOLAB(pcop)->offset = 0;
2188 pcop->name = Safe_strdup(s);
2190 ((pCodeOpLabel *)pcop)->key = key;
2192 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2196 /*-----------------------------------------------------------------*/
2197 /*-----------------------------------------------------------------*/
2198 pCodeOp *newpCodeOpLit(int lit)
2204 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2205 pcop->type = PO_LITERAL;
2209 sprintf(s,"0x%02x",lit);
2211 pcop->name = Safe_strdup(s);
2214 ((pCodeOpLit *)pcop)->lit = lit;
2219 /*-----------------------------------------------------------------*/
2220 /*-----------------------------------------------------------------*/
2221 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2225 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2226 pcop->type = PO_IMMEDIATE;
2229 pcop->name = Safe_strdup(name);
2232 r = dirregWithName(name);
2236 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2237 PCOI(pcop)->rIdx = r->rIdx;
2239 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2240 PCOI(pcop)->rIdx = -1;
2242 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2247 PCOI(pcop)->index = index;
2248 PCOI(pcop)->offset = offset;
2249 PCOI(pcop)->_const = code_space;
2250 PCOI(pcop)->_function = is_func;
2255 /*-----------------------------------------------------------------*/
2256 /*-----------------------------------------------------------------*/
2257 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2263 if(!pcwb || !subtype) {
2264 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2268 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2269 pcop->type = PO_WILD;
2270 sprintf(s,"%%%d",id);
2271 pcop->name = Safe_strdup(s);
2273 PCOW(pcop)->id = id;
2274 PCOW(pcop)->pcwb = pcwb;
2275 PCOW(pcop)->subtype = subtype;
2276 PCOW(pcop)->matched = NULL;
2280 /*-----------------------------------------------------------------*/
2281 /* Find a symbol with matching name */
2282 /*-----------------------------------------------------------------*/
2283 static symbol *symFindWithName(memmap * map, const char *name)
2287 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2288 if (sym->rname && (strcmp(sym->rname,name)==0))
2294 /*-----------------------------------------------------------------*/
2295 /*-----------------------------------------------------------------*/
2296 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2301 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2302 pcop->type = PO_GPR_BIT;
2304 PCORB(pcop)->bit = ibit;
2305 PCORB(pcop)->inBitSpace = inBitSpace;
2307 if (name) r = regFindWithName(name);
2309 // Register has not been allocated - check for symbol information
2311 sym = symFindWithName(bit, name);
2312 if (!sym) sym = symFindWithName(sfrbit, name);
2313 if (!sym) sym = symFindWithName(sfr, name);
2315 r = allocNewDirReg(sym->etype,name);
2321 PCOR(pcop)->rIdx = r->rIdx;
2323 pcop->name = Safe_strdup(name);
2324 PCOR(pcop)->r = NULL;
2325 PCOR(pcop)->rIdx = 0;
2330 /*-----------------------------------------------------------------*
2331 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2333 * If rIdx >=0 then a specific register from the set of registers
2334 * will be selected. If rIdx <0, then a new register will be searched
2336 *-----------------------------------------------------------------*/
2338 pCodeOp *newpCodeOpReg(int rIdx)
2342 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2347 PCOR(pcop)->rIdx = rIdx;
2348 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2350 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2353 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2357 pcop->type = PCOR(pcop)->r->pc_type;
2362 pCodeOp *newpCodeOpRegFromStr(char *name)
2366 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2367 PCOR(pcop)->r = allocRegByName(name, 1);
2368 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2369 pcop->type = PCOR(pcop)->r->pc_type;
2370 pcop->name = PCOR(pcop)->r->name;
2375 pCodeOp *newpCodeOpStr(char *name)
2379 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2380 pcop->type = PO_STR;
2381 pcop->name = Safe_strdup(name);
2383 PCOS(pcop)->isPublic = 0;
2389 /*-----------------------------------------------------------------*/
2390 /*-----------------------------------------------------------------*/
2392 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2399 pcop = newpCodeOpBit(name, -1,0);
2403 pcop = newpCodeOpLit(-1);
2407 pcop = newpCodeOpLabel(NULL,-1);
2411 pcop = newpCodeOpReg(-1);
2414 case PO_GPR_POINTER:
2415 case PO_GPR_REGISTER:
2417 pcop = newpCodeOpRegFromStr(name);
2419 pcop = newpCodeOpReg(-1);
2423 pcop = newpCodeOpStr(name);
2427 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2430 pcop->name = Safe_strdup(name);
2438 /*-----------------------------------------------------------------*/
2439 /*-----------------------------------------------------------------*/
2440 void pCodeConstString(char *name, char *value)
2444 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2449 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2453 sprintf(buffer,"; %s = %s",name,value);
2455 addpCode2pBlock(pb,newpCodeCharP(buffer));
2456 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2459 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2465 /*-----------------------------------------------------------------*/
2466 /*-----------------------------------------------------------------*/
2467 void pCodeReadCodeTable(void)
2471 fprintf(stderr, " %s\n",__FUNCTION__);
2473 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2477 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2478 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2479 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2480 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2482 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2483 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2484 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2485 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2490 /*-----------------------------------------------------------------*/
2491 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2492 /*-----------------------------------------------------------------*/
2493 void addpCode2pBlock(pBlock *pb, pCode *pc)
2500 /* If this is the first pcode to be added to a block that
2501 * was initialized with a NULL pcode, then go ahead and
2502 * make this pcode the head and tail */
2503 pb->pcHead = pb->pcTail = pc;
2506 pb->pcTail->next = pc;
2508 pc->prev = pb->pcTail;
2515 /*-----------------------------------------------------------------*/
2516 /* addpBlock - place a pBlock into the pFile */
2517 /*-----------------------------------------------------------------*/
2518 void addpBlock(pBlock *pb)
2520 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2523 /* First time called, we'll pass through here. */
2524 //_ALLOC(the_pFile,sizeof(pFile));
2525 the_pFile = Safe_calloc(1,sizeof(pFile));
2526 the_pFile->pbHead = the_pFile->pbTail = pb;
2527 the_pFile->functions = NULL;
2531 the_pFile->pbTail->next = pb;
2532 pb->prev = the_pFile->pbTail;
2534 the_pFile->pbTail = pb;
2537 /*-----------------------------------------------------------------*/
2538 /* removepBlock - remove a pBlock from the pFile */
2539 /*-----------------------------------------------------------------*/
2540 void removepBlock(pBlock *pb)
2548 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2550 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2553 if(pbs == the_pFile->pbHead)
2554 the_pFile->pbHead = pbs->next;
2556 if (pbs == the_pFile->pbTail)
2557 the_pFile->pbTail = pbs->prev;
2560 pbs->next->prev = pbs->prev;
2563 pbs->prev->next = pbs->next;
2570 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2574 /*-----------------------------------------------------------------*/
2575 /* printpCode - write the contents of a pCode to a file */
2576 /*-----------------------------------------------------------------*/
2577 void printpCode(FILE *of, pCode *pc)
2588 fprintf(of,"warning - unable to print pCode\n");
2591 /*-----------------------------------------------------------------*/
2592 /* printpBlock - write the contents of a pBlock to a file */
2593 /*-----------------------------------------------------------------*/
2594 void printpBlock(FILE *of, pBlock *pb)
2604 for(pc = pb->pcHead; pc; pc = pc->next)
2609 /*-----------------------------------------------------------------*/
2611 /* pCode processing */
2615 /*-----------------------------------------------------------------*/
2617 void unlinkpCode(pCode *pc)
2623 fprintf(stderr,"Unlinking: ");
2624 printpCode(stderr, pc);
2627 pc->prev->next = pc->next;
2629 pc->next->prev = pc->prev;
2631 pc->prev = pc->next = NULL;
2635 /*-----------------------------------------------------------------*/
2636 /*-----------------------------------------------------------------*/
2638 static void genericDestruct(pCode *pc)
2644 /* For instructions, tell the register (if there's one used)
2645 * that it's no longer needed */
2646 regs *reg = getRegFromInstruction(pc);
2648 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2651 /* Instead of deleting the memory used by this pCode, mark
2652 * the object as bad so that if there's a pointer to this pCode
2653 * dangling around somewhere then (hopefully) when the type is
2654 * checked we'll catch it.
2659 addpCode2pBlock(pb_dead_pcodes, pc);
2666 /*-----------------------------------------------------------------*/
2667 /* Copies the pCodeInstruction flow pointer from source pCode */
2668 /*-----------------------------------------------------------------*/
2669 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2671 pCodeFlow *pcflow = 0;
2672 for (p=pcs; p; p=p->prev) {
2674 pcflow = PCI(p)->pcflow;
2678 pcflow = (pCodeFlow*)p;
2682 PCI(pcd)->pcflow = pcflow;
2685 /*-----------------------------------------------------------------*/
2686 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2687 /* into the pCode chain containing pc1 */
2688 /*-----------------------------------------------------------------*/
2689 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2695 pc2->next = pc1->next;
2697 pc1->next->prev = pc2;
2703 /* If this is an instrution type propogate the flow */
2705 CopyFlow(PCI(pc2),pc1);
2708 /*------------------------------------------------------------------*/
2709 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2710 /* into the pCode chain containing pc1 */
2711 /*------------------------------------------------------------------*/
2712 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2718 pc2->prev = pc1->prev;
2720 pc1->prev->next = pc2;
2726 /* If this is an instrution type propogate the flow */
2728 CopyFlow(PCI(pc2),pc1);
2731 /*-----------------------------------------------------------------*/
2732 /* pCodeOpCopy - copy a pcode operator */
2733 /*-----------------------------------------------------------------*/
2734 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2736 pCodeOp *pcopnew=NULL;
2741 switch(pcop->type) {
2744 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2745 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2746 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2747 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2752 /* Here we expand the wild card into the appropriate type: */
2753 /* By recursively calling pCodeOpCopy */
2754 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2755 if(PCOW(pcop)->matched)
2756 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2759 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2760 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2761 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2768 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2769 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2770 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2774 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2775 PCOI(pcopnew)->index = PCOI(pcop)->index;
2776 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2777 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2778 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2782 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2783 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2784 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2789 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2790 PCOR(pcopnew)->r = PCOR(pcop)->r;
2791 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2792 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2796 case PO_GPR_POINTER:
2797 case PO_GPR_REGISTER:
2801 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2802 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2803 PCOR(pcopnew)->r = PCOR(pcop)->r;
2804 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2805 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2806 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2810 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2811 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2812 PCOR(pcopnew)->r = PCOR(pcop)->r;
2813 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2814 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2817 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2818 case PO_SFR_REGISTER:
2826 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2827 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2831 pcopnew->type = pcop->type;
2833 pcopnew->name = Safe_strdup(pcop->name);
2835 pcopnew->name = NULL;
2840 /*-----------------------------------------------------------------*/
2841 /* popCopyReg - copy a pcode operator */
2842 /*-----------------------------------------------------------------*/
2843 pCodeOp *popCopyReg(pCodeOpReg *pc)
2847 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2848 pcor->pcop.type = pc->pcop.type;
2850 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2851 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2853 pcor->pcop.name = NULL;
2855 if (pcor->pcop.type == PO_IMMEDIATE){
2856 PCOL(pcor)->lit = PCOL(pc)->lit;
2859 pcor->rIdx = pc->rIdx;
2863 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2868 /*-----------------------------------------------------------------*/
2869 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2870 /*-----------------------------------------------------------------*/
2871 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2873 pCodeInstruction *new_pci;
2876 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2878 new_pci = PCI(newpCode(pci->op,pci->pcop));
2880 new_pci->pc.pb = pci->pc.pb;
2881 new_pci->from = pci->from;
2882 new_pci->to = pci->to;
2883 new_pci->label = pci->label;
2884 new_pci->pcflow = pci->pcflow;
2886 return PCODE(new_pci);
2889 /*-----------------------------------------------------------------*/
2890 /*-----------------------------------------------------------------*/
2891 void pCodeDeleteChain(pCode *f,pCode *t)
2896 DFPRINTF((stderr,"delete pCode:\n"));
2898 //f->print(stderr,f);
2899 //f->delete(f); this dumps core...
2904 /*-----------------------------------------------------------------*/
2905 /*-----------------------------------------------------------------*/
2906 void pBlockRegs(FILE *of, pBlock *pb)
2911 r = setFirstItem(pb->tregisters);
2913 r = setNextItem(pb->tregisters);
2918 /*-----------------------------------------------------------------*/
2919 /*-----------------------------------------------------------------*/
2920 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2925 int use_buffer = 1; // copy the string to the passed buffer pointer
2930 use_buffer = 0; // Don't bother copying the string to the buffer.
2934 switch(pcop->type) {
2938 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2941 //return PCOR(pcop)->r->name;
2945 if (PCOR(pcop)->r->type == REG_STK)
2946 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2948 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2951 SAFE_snprintf(&buffer,&size,"%s",r->name);
2961 if(PCOI(pcop)->_const) {
2963 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2964 switch(PCOI(pcop)->offset) {
2966 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2969 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2972 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2975 8 * PCOI(pcop)->offset );
2978 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2981 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2982 SAFE_snprintf(&s,&size,"(%s + %d)",
2984 PCOI(pcop)->index );
2986 switch(PCOI(pcop)->offset) {
2988 SAFE_snprintf(&s,&size,"%s",pcop->name);
2991 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2994 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3003 //size = sizeof(buffer);
3004 if( PCOR(pcop)->instance) {
3005 SAFE_snprintf(&s,&size,"(%s + %d)",
3007 PCOR(pcop)->instance );
3008 //fprintf(stderr,"PO_DIR %s\n",buffer);
3010 SAFE_snprintf(&s,&size,"%s",pcop->name);
3016 if(PCOLAB(pcop)->offset == 1)
3017 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3019 SAFE_snprintf(&s,&size,"%s",pcop->name);
3026 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3029 return PCOR(pcop)->r->name;
3032 /* fall through to the default case */
3036 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3044 printf("PIC port internal warning: (%s:%d) %s not found\n",
3049 return "NO operand";
3053 /*-----------------------------------------------------------------*/
3054 /*-----------------------------------------------------------------*/
3055 static char *get_op_from_instruction( pCodeInstruction *pcc)
3059 return get_op(pcc->pcop,NULL,0);
3061 return ("ERROR Null: get_op_from_instruction");
3065 /*-----------------------------------------------------------------*/
3066 /*-----------------------------------------------------------------*/
3067 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3069 fprintf(of,"pcodeopprint- not implemented\n");
3072 /*-----------------------------------------------------------------*/
3073 /* pCode2str - convert a pCode instruction to string */
3074 /*-----------------------------------------------------------------*/
3075 char *pCode2str(char *str, size_t size, pCode *pc)
3083 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3085 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3087 if(PCI(pc)->isBitInst) {
3088 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3089 char *name = PCI(pc)->pcop->name;
3091 name = PCOR(PCI(pc)->pcop)->r->name;
3092 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3093 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3095 SAFE_snprintf(&s,&size,"%s,%d", name,
3096 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3097 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3098 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3100 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3101 //PCI(pc)->pcop->t.bit );
3103 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3104 if( PCI(pc)->num_ops == 2)
3105 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3107 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3109 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3110 if( PCI(pc)->num_ops == 2)
3111 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3118 /* assuming that comment ends with a \n */
3119 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3123 /* assuming that inline code ends with a \n */
3124 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3128 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3131 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3134 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3137 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3140 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3143 if(PCAD(pc)->directive) {
3144 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3145 } else if(PCAD(pc)->arg) {
3146 /* special case to handle inline labels without a tab */
3147 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3152 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3158 /*-----------------------------------------------------------------*/
3159 /* genericPrint - the contents of a pCode to a file */
3160 /*-----------------------------------------------------------------*/
3161 static void genericPrint(FILE *of, pCode *pc)
3168 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3172 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3176 // If the opcode has a label, print that first
3179 pCodeInstruction *pci = PCI(pc);
3180 pBranch *pbl = pci->label;
3181 while(pbl && pbl->pc) {
3182 if(pbl->pc->type == PC_LABEL)
3183 pCodePrintLabel(of, pbl->pc);
3188 genericPrint(of,PCODE(pci->cline));
3191 pCode2str(str, 256, pc);
3193 fprintf(of,"%s",str);
3197 pCodeOpReg *pcor = PCOR(pci->pcop);
3198 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3200 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3201 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3202 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3207 pBranch *dpb = pc->to; // debug
3209 switch ( dpb->pc->type) {
3211 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3214 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3217 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3220 fprintf(of, "\t;flow");
3234 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3235 if(PCW(pc)->pci.label)
3236 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3238 if(PCW(pc)->operand) {
3239 fprintf(of,";\toperand ");
3240 pCodeOpPrint(of,PCW(pc)->operand );
3246 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3247 if(PCFL(pc)->ancestor)
3248 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3254 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3259 pBranch *pbl = PCAD(pc)->pci.label;
3260 while(pbl && pbl->pc) {
3261 if(pbl->pc->type == PC_LABEL)
3262 pCodePrintLabel(of, pbl->pc);
3266 if(PCAD(pc)->directive) {
3267 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3270 /* special case to handle inline labels without tab */
3271 fprintf(of, "%s\n", PCAD(pc)->arg);
3277 fprintf(of,"unknown pCode type %d\n",pc->type);
3281 /*-----------------------------------------------------------------*/
3282 /* pCodePrintFunction - prints function begin/end */
3283 /*-----------------------------------------------------------------*/
3285 static void pCodePrintFunction(FILE *of, pCode *pc)
3291 if( ((pCodeFunction *)pc)->modname)
3292 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3294 if(PCF(pc)->fname) {
3295 pBranch *exits = PCF(pc)->to;
3297 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3300 exits = exits->next;
3303 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3306 if((PCF(pc)->from &&
3307 PCF(pc)->from->pc->type == PC_FUNCTION &&
3308 PCF(PCF(pc)->from->pc)->fname) )
3309 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3311 fprintf(of,"; exit point [can't find entry point]\n");
3314 /*-----------------------------------------------------------------*/
3315 /* pCodePrintLabel - prints label */
3316 /*-----------------------------------------------------------------*/
3318 static void pCodePrintLabel(FILE *of, pCode *pc)
3325 fprintf(of,"%s\n",PCL(pc)->label);
3326 else if (PCL(pc)->key >=0)
3327 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3329 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3333 /*-----------------------------------------------------------------*/
3334 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3335 /* remove it if it is found. */
3336 /*-----------------------------------------------------------------*/
3337 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3343 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3344 b = PCI(pcl)->label;
3346 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3350 //fprintf (stderr, "%s \n",__FUNCTION__);
3351 //pcl->print(stderr,pcl);
3352 //pc->print(stderr,pc);
3355 //fprintf (stderr, "found label\n");
3359 bprev->next = b->next; /* Not first pCode in chain */
3363 PCI(pcl)->label = b->next; /* First pCode in chain */
3366 return; /* A label can't occur more than once */
3373 /*-----------------------------------------------------------------*/
3374 /*-----------------------------------------------------------------*/
3375 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3394 /*-----------------------------------------------------------------*/
3395 /* pBranchLink - given two pcodes, this function will link them */
3396 /* together through their pBranches */
3397 /*-----------------------------------------------------------------*/
3398 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3402 // Declare a new branch object for the 'from' pCode.
3404 //_ALLOC(b,sizeof(pBranch));
3405 b = Safe_calloc(1,sizeof(pBranch));
3406 b->pc = PCODE(t); // The link to the 'to' pCode.
3409 f->to = pBranchAppend(f->to,b);
3411 // Now do the same for the 'to' pCode.
3413 //_ALLOC(b,sizeof(pBranch));
3414 b = Safe_calloc(1,sizeof(pBranch));
3418 t->from = pBranchAppend(t->from,b);
3423 /*-----------------------------------------------------------------*/
3424 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3426 /*-----------------------------------------------------------------*/
3427 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3440 /*-----------------------------------------------------------------*/
3441 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3442 /*-----------------------------------------------------------------*/
3443 static void pCodeUnlink(pCode *pc)
3448 if(!pc->prev || !pc->next) {
3449 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3453 /* first remove the pCode from the chain */
3454 pc->prev->next = pc->next;
3455 pc->next->prev = pc->prev;
3457 /* Now for the hard part... */
3459 /* Remove the branches */
3463 pc1 = pb1->pc; /* Get the pCode that branches to the
3464 * one we're unlinking */
3466 /* search for the link back to this pCode (the one we're
3468 if(pb2 = pBranchFind(pc1->to,pc)) {
3469 pb2->pc = pc->to->pc; // make the replacement
3471 /* if the pCode we're unlinking contains multiple 'to'
3472 * branches (e.g. this a skip instruction) then we need
3473 * to copy these extra branches to the chain. */
3475 pBranchAppend(pb2, pc->to->next);
3484 /*-----------------------------------------------------------------*/
3485 /*-----------------------------------------------------------------*/
3487 static void genericAnalyze(pCode *pc)
3497 // Go through the pCodes that are in pCode chain and link
3498 // them together through the pBranches. Note, the pCodes
3499 // are linked together as a contiguous stream like the
3500 // assembly source code lines. The linking here mimics this
3501 // except that comments are not linked in.
3503 pCode *npc = pc->next;
3505 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3506 pBranchLink(pc,npc);
3511 /* reached the end of the pcode chain without finding
3512 * an instruction we could link to. */
3516 fprintf(stderr,"analyze PC_FLOW\n");
3520 fprintf(stderr,";A bad pCode is being used\n");
3526 /*-----------------------------------------------------------------*/
3527 /*-----------------------------------------------------------------*/
3528 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3532 if(pc->type == PC_LABEL) {
3533 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3536 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3537 pbr = PCI(pc)->label;
3539 if(pbr->pc->type == PC_LABEL) {
3540 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3550 /*-----------------------------------------------------------------*/
3551 /*-----------------------------------------------------------------*/
3552 int checkLabel(pCode *pc)
3556 if(pc && isPCI(pc)) {
3557 pbr = PCI(pc)->label;
3559 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3569 /*-----------------------------------------------------------------*/
3570 /* findLabelinpBlock - Search the pCode for a particular label */
3571 /*-----------------------------------------------------------------*/
3572 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3579 for(pc = pb->pcHead; pc; pc = pc->next)
3580 if(compareLabel(pc,pcop_label))
3586 /*-----------------------------------------------------------------*/
3587 /* findLabel - Search the pCode for a particular label */
3588 /*-----------------------------------------------------------------*/
3589 pCode * findLabel(pCodeOpLabel *pcop_label)
3597 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3598 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3602 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3606 /*-----------------------------------------------------------------*/
3607 /* findNextpCode - given a pCode, find the next of type 'pct' */
3608 /* in the linked list */
3609 /*-----------------------------------------------------------------*/
3610 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3623 /*-----------------------------------------------------------------*/
3624 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3625 /* in the linked list */
3626 /*-----------------------------------------------------------------*/
3627 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3631 if(pc->type == pct) {
3633 static unsigned int stop;
3635 stop++; // Place break point here
3646 /*-----------------------------------------------------------------*/
3647 /* findNextInstruction - given a pCode, find the next instruction */
3648 /* in the linked list */
3649 /*-----------------------------------------------------------------*/
3650 pCode * findNextInstruction(pCode *pci)
3655 if((pc->type == PC_OPCODE)
3656 || (pc->type == PC_WILD)
3657 || (pc->type == PC_ASMDIR))
3661 fprintf(stderr,"findNextInstruction: ");
3662 printpCode(stderr, pc);
3667 //fprintf(stderr,"Couldn't find instruction\n");
3671 /*-----------------------------------------------------------------*/
3672 /* findNextInstruction - given a pCode, find the next instruction */
3673 /* in the linked list */
3674 /*-----------------------------------------------------------------*/
3675 pCode * findPrevInstruction(pCode *pci)
3681 if((pc->type == PC_OPCODE)
3682 || (pc->type == PC_WILD)
3683 || (pc->type == PC_ASMDIR))
3688 fprintf(stderr,"pic16_findPrevInstruction: ");
3689 printpCode(stderr, pc);
3694 //fprintf(stderr,"Couldn't find instruction\n");
3698 /*-----------------------------------------------------------------*/
3699 /* findFunctionEnd - given a pCode find the end of the function */
3700 /* that contains it */
3701 /*-----------------------------------------------------------------*/
3702 pCode * findFunctionEnd(pCode *pc)
3705 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3711 fprintf(stderr,"Couldn't find function end\n");
3716 /*-----------------------------------------------------------------*/
3717 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3718 /* instruction with which it is associated. */
3719 /*-----------------------------------------------------------------*/
3720 static void AnalyzeLabel(pCode *pc)
3729 static void AnalyzeGOTO(pCode *pc)
3732 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3736 static void AnalyzeSKIP(pCode *pc)
3739 pBranchLink(pc,findNextInstruction(pc->next));
3740 pBranchLink(pc,findNextInstruction(pc->next->next));
3744 static void AnalyzeRETURN(pCode *pc)
3747 // branch_link(pc,findFunctionEnd(pc->next));
3753 /*-----------------------------------------------------------------*/
3754 /*-----------------------------------------------------------------*/
3755 regs * getRegFromInstruction(pCode *pc)
3761 PCI(pc)->num_ops == 0 )
3764 switch(PCI(pc)->pcop->type) {
3767 return PCOR(PCI(pc)->pcop)->r;
3771 return PCOR(PCI(pc)->pcop)->r;
3774 r = PCOI(PCI(pc)->pcop)->r;
3777 return dirregWithName(PCI(pc)->pcop->name);
3780 r = PCOR(PCI(pc)->pcop)->r;
3783 return dirregWithName(PCI(pc)->pcop->name);
3785 case PO_GPR_REGISTER:
3787 r = PCOR(PCI(pc)->pcop)->r;
3790 return dirregWithName(PCI(pc)->pcop->name);
3802 /*-----------------------------------------------------------------*/
3803 /*-----------------------------------------------------------------*/
3805 void AnalyzepBlock(pBlock *pb)
3812 /* Find all of the registers used in this pBlock
3813 * by looking at each instruction and examining it's
3816 for(pc = pb->pcHead; pc; pc = pc->next) {
3818 /* Is this an instruction with operands? */
3819 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3821 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3822 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3824 /* Loop through all of the registers declared so far in
3825 this block and see if we find this one there */
3827 regs *r = setFirstItem(pb->tregisters);
3830 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3831 PCOR(PCI(pc)->pcop)->r = r;
3834 r = setNextItem(pb->tregisters);
3838 /* register wasn't found */
3839 //r = Safe_calloc(1, sizeof(regs));
3840 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3841 //addSet(&pb->tregisters, r);
3842 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3843 //PCOR(PCI(pc)->pcop)->r = r;
3844 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3846 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3849 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3850 if(PCOR(PCI(pc)->pcop)->r) {
3851 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3852 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3854 if(PCI(pc)->pcop->name)
3855 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3857 fprintf(stderr,"ERROR: NULL register\n");
3866 /*-----------------------------------------------------------------*/
3868 /*-----------------------------------------------------------------*/
3869 void InsertpFlow(pCode *pc, pCode **pflow)
3872 PCFL(*pflow)->end = pc;
3874 if(!pc || !pc->next)
3877 *pflow = newpCodeFlow();
3878 pCodeInsertAfter(pc, *pflow);
3881 /*-----------------------------------------------------------------*/
3882 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3883 /* the flow blocks. */
3885 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3886 * point the instruction flow changes.
3888 /*-----------------------------------------------------------------*/
3889 void BuildFlow(pBlock *pb)
3892 pCode *last_pci=NULL;
3899 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3900 /* Insert a pCodeFlow object at the beginning of a pBlock */
3902 InsertpFlow(pb->pcHead, &pflow);
3904 //pflow = newpCodeFlow(); /* Create a new Flow object */
3905 //pflow->next = pb->pcHead; /* Make the current head the next object */
3906 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3907 //pb->pcHead = pflow; /* Make the Flow object the head */
3910 for( pc = findNextInstruction(pb->pcHead);
3912 pc=findNextInstruction(pc)) {
3915 PCI(pc)->pcflow = PCFL(pflow);
3917 //fprintf(stderr," build: ");
3918 //pflow->print(stderr,pflow);
3920 if( PCI(pc)->isSkip) {
3922 /* The two instructions immediately following this one
3923 * mark the beginning of a new flow segment */
3925 while(pc && PCI(pc)->isSkip) {
3927 PCI(pc)->pcflow = PCFL(pflow);
3931 InsertpFlow(pc, &pflow);
3932 pc=findNextInstruction(pc->next);
3940 PCI(pc)->pcflow = PCFL(pflow);
3942 InsertpFlow(pc, &pflow);
3944 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3946 InsertpFlow(pc, &pflow);
3949 } else if (checkLabel(pc)) {
3951 /* This instruction marks the beginning of a
3952 * new flow segment */
3957 /* If the previous pCode is not a flow object, then
3958 * insert a new flow object. (This check prevents
3959 * two consecutive flow objects from being insert in
3960 * the case where a skip instruction preceeds an
3961 * instruction containing a label.) */
3963 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3964 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3966 PCI(pc)->pcflow = PCFL(pflow);
3973 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3975 PCFL(pflow)->end = pb->pcTail;
3978 /*-------------------------------------------------------------------*/
3979 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3980 /* the flow blocks. */
3982 * unBuildFlow removes pCodeFlow objects from a pCode chain
3984 /*-----------------------------------------------------------------*/
3985 void unBuildFlow(pBlock *pb)
4000 if(PCI(pc)->pcflow) {
4001 //free(PCI(pc)->pcflow);
4002 PCI(pc)->pcflow = NULL;
4005 } else if(isPCFL(pc) )
4014 /*-----------------------------------------------------------------*/
4015 /*-----------------------------------------------------------------*/
4016 void dumpCond(int cond)
4019 static char *pcc_str[] = {
4033 int ncond = sizeof(pcc_str) / sizeof(char *);
4036 fprintf(stderr, "0x%04X\n",cond);
4038 for(i=0,j=1; i<ncond; i++, j<<=1)
4040 fprintf(stderr, " %s\n",pcc_str[i]);
4044 /*-----------------------------------------------------------------*/
4045 /*-----------------------------------------------------------------*/
4046 void FlowStats(pCodeFlow *pcflow)
4054 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4056 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4059 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4064 fprintf(stderr, " FlowStats inCond: ");
4065 dumpCond(pcflow->inCond);
4066 fprintf(stderr, " FlowStats outCond: ");
4067 dumpCond(pcflow->outCond);
4071 /*-----------------------------------------------------------------*
4072 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4073 * if it affects the banking bits.
4075 * return: -1 == Banking bits are unaffected by this pCode.
4077 * return: > 0 == Banking bits are affected.
4079 * If the banking bits are affected, then the returned value describes
4080 * which bits are affected and how they're affected. The lower half
4081 * of the integer maps to the bits that are affected, the upper half
4082 * to whether they're set or cleared.
4084 *-----------------------------------------------------------------*/
4086 #define SET_BANK_BIT (1 << 16)
4087 #define CLR_BANK_BIT 0
4089 static int isBankInstruction(pCode *pc)
4097 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4099 // Check to see if the register banks are changing
4100 if(PCI(pc)->isModReg) {
4102 pCodeOp *pcop = PCI(pc)->pcop;
4103 switch(PCI(pc)->op) {
4106 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4107 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4108 return SET_BANK_BIT | PIC_RP0_BIT;
4111 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4112 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4113 return CLR_BANK_BIT | PIC_RP0_BIT;
4118 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4119 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4120 return CLR_BANK_BIT | PIC_RP1_BIT;
4122 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4123 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4124 return CLR_BANK_BIT | PIC_RP1_BIT;
4128 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4129 //genericPrint(stderr, pc);
4140 /*-----------------------------------------------------------------*/
4141 /*-----------------------------------------------------------------*/
4143 static void FillFlow(pCodeFlow *pcflow)
4151 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4153 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4156 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4163 isBankInstruction(pc);
4165 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4168 fprintf(stderr, " FillFlow - Bad end of flow\n");
4170 fprintf(stderr, " FillFlow - Ending flow with\n ");
4171 pc->print(stderr,pc);
4174 fprintf(stderr, " FillFlow inCond: ");
4175 dumpCond(pcflow->inCond);
4176 fprintf(stderr, " FillFlow outCond: ");
4177 dumpCond(pcflow->outCond);
4182 /*-----------------------------------------------------------------*/
4183 /*-----------------------------------------------------------------*/
4184 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4186 pCodeFlowLink *fromLink, *toLink;
4188 if(!from || !to || !to->pcflow || !from->pcflow)
4191 fromLink = newpCodeFlowLink(from->pcflow);
4192 toLink = newpCodeFlowLink(to->pcflow);
4194 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4195 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4199 /*-----------------------------------------------------------------*
4200 * void LinkFlow(pBlock *pb)
4202 * In BuildFlow, the PIC code has been partitioned into contiguous
4203 * non-branching segments. In LinkFlow, we determine the execution
4204 * order of these segments. For example, if one of the segments ends
4205 * with a skip, then we know that there are two possible flow segments
4206 * to which control may be passed.
4207 *-----------------------------------------------------------------*/
4208 void LinkFlow(pBlock *pb)
4214 //fprintf(stderr,"linkflow \n");
4216 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4218 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4221 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4223 //fprintf(stderr," link: ");
4224 //pcflow->print(stderr,pcflow);
4226 //FillFlow(PCFL(pcflow));
4228 pc = PCFL(pcflow)->end;
4230 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4231 if(isPCI_SKIP(pc)) {
4232 //fprintf(stderr, "ends with skip\n");
4233 //pc->print(stderr,pc);
4234 pct=findNextInstruction(pc->next);
4235 LinkFlow_pCode(PCI(pc),PCI(pct));
4236 pct=findNextInstruction(pct->next);
4237 LinkFlow_pCode(PCI(pc),PCI(pct));
4241 if(isPCI_BRANCH(pc)) {
4242 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4244 //fprintf(stderr, "ends with branch\n ");
4245 //pc->print(stderr,pc);
4247 if(!(pcol && isPCOLAB(pcol))) {
4248 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4249 pc->print(stderr,pc);
4250 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4255 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4256 LinkFlow_pCode(PCI(pc),PCI(pct));
4258 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4259 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4260 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4266 //fprintf(stderr, "ends with non-branching instruction:\n");
4267 //pc->print(stderr,pc);
4269 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4275 //fprintf(stderr, "ends with unknown\n");
4276 //pc->print(stderr,pc);
4280 //fprintf(stderr, "ends with nothing: ERROR\n");
4284 /*-----------------------------------------------------------------*/
4285 /*-----------------------------------------------------------------*/
4287 /*-----------------------------------------------------------------*/
4288 /*-----------------------------------------------------------------*/
4289 int isPCinFlow(pCode *pc, pCode *pcflow)
4295 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4298 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4304 /*-----------------------------------------------------------------*/
4305 /*-----------------------------------------------------------------*/
4307 static void BanksUsedFlow2(pCode *pcflow)
4316 if(!isPCFL(pcflow)) {
4317 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4321 pc = findNextInstruction(pcflow->next);
4323 PCFL(pcflow)->lastBank = -1;
4325 while(isPCinFlow(pc,pcflow)) {
4327 int bank_selected = isBankInstruction(pc);
4329 //if(PCI(pc)->pcflow)
4330 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4332 if(bank_selected > 0) {
4333 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4335 // This instruction is modifying banking bits before accessing registers
4337 PCFL(pcflow)->firstBank = -1;
4339 if(PCFL(pcflow)->lastBank == -1)
4340 PCFL(pcflow)->lastBank = 0;
4342 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4343 if(bank_selected & SET_BANK_BIT)
4344 PCFL(pcflow)->lastBank |= bank;
4348 reg = getRegFromInstruction(pc);
4350 if(reg && !isREGinBank(reg, bank)) {
4351 int allbanks = REGallBanks(reg);
4353 PCFL(pcflow)->firstBank = allbanks;
4355 PCFL(pcflow)->lastBank = allbanks;
4362 pc = findNextInstruction(pc->next);
4365 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4366 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4369 /*-----------------------------------------------------------------*/
4370 /*-----------------------------------------------------------------*/
4372 static void BanksUsedFlow(pBlock *pb)
4377 //pb->pcHead->print(stderr, pb->pcHead);
4379 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4380 //pcflow->print(stderr,pcflow);
4382 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4384 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4386 BanksUsedFlow2(pcflow);
4392 /*-----------------------------------------------------------------*/
4393 /* Inserts a new pCodeInstruction before an existing one */
4394 /*-----------------------------------------------------------------*/
4395 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4398 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4400 /* Move the label, if there is one */
4403 new_pci->label = pci->label;
4407 /* Move the C code comment, if there is one */
4410 new_pci->cline = pci->cline;
4414 /* The new instruction has the same pcflow block */
4415 new_pci->pcflow = pci->pcflow;
4419 /*-----------------------------------------------------------------*/
4420 /*-----------------------------------------------------------------*/
4421 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4425 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4427 insertPCodeInstruction(pci, PCI(new_pc));
4430 /*-----------------------------------------------------------------*/
4431 /*-----------------------------------------------------------------*/
4432 static void insertBankSel(pCodeInstruction *pci, const char *name)
4436 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4437 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4438 if (pcop->name == 0)
4439 pcop->name = strdup(name);
4440 new_pc = newpCode(POC_BANKSEL, pcop);
4442 insertPCodeInstruction(pci, PCI(new_pc));
4445 /*-----------------------------------------------------------------*/
4446 /* If the register is a fixed known addess then we can assign the */
4447 /* bank selection bits. Otherwise the linker is going to assign */
4448 /* the register location and thus has to set bank selection bits */
4449 /* through the banksel directive. */
4450 /* One critical assumption here is that within this C module all */
4451 /* the locally allocated registers are in the same udata sector. */
4452 /* Therefore banksel is only called for external registers or the */
4453 /* first time a local register is encountered. */
4454 /*-----------------------------------------------------------------*/
4455 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4456 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4459 int a = reg->alias>>7;
4461 return cur_bank; // This register is available in all banks
4462 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4463 return cur_bank; // This register is available in banks 0 & 1
4465 if (reg->address&0x80) {
4466 if ((cur_bank==1)||(cur_bank==3)) {
4467 return cur_bank; // This register is available in banks 1 & 3
4470 if ((cur_bank==0)||(cur_bank==1)) {
4471 return cur_bank; // This register is available in banks 0 & 2
4476 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4478 LastRegIdx = reg->rIdx;
4481 bank = REG_BANK(reg);
4482 } else if (reg->isExtern) {
4483 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4485 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4487 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.
4488 return 'L'; // Local registers are presumed to be in same linker assigned bank
4489 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4490 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4491 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4492 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4493 } 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
4494 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4495 if (getMaxRam()&0x100)
4496 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4497 } else { // Current bank and new register banks known - can set bank bits
4498 switch((cur_bank^bank) & 3) {
4502 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4505 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4508 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4509 if (getMaxRam()&0x100)
4510 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4518 /*-----------------------------------------------------------------*/
4519 /* Check for bank selection pcodes instructions and modify */
4520 /* cur_bank to match. */
4521 /*-----------------------------------------------------------------*/
4522 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4524 if (isSTATUS_REG(reg)) {
4526 if (PCI(pc)->op == POC_BCF) {
4527 int old_bank = *cur_bank;
4528 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4529 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4530 if (*cur_bank & ~(0x3))
4533 *cur_bank = *cur_bank&0x2;
4534 LastRegIdx = reg->rIdx;
4535 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4536 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4537 if (*cur_bank & ~(0x3))
4540 *cur_bank = *cur_bank&0x1;
4541 LastRegIdx = reg->rIdx;
4543 return old_bank != *cur_bank;
4546 if (PCI(pc)->op == POC_BSF) {
4547 int old_bank = *cur_bank;
4548 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4549 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4550 if (*cur_bank & ~(0x3))
4553 *cur_bank = (*cur_bank&0x2) | 0x1;
4554 LastRegIdx = reg->rIdx;
4555 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4556 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4557 if (*cur_bank & ~(0x3))
4560 *cur_bank = (*cur_bank&0x1) | 0x2;
4561 LastRegIdx = reg->rIdx;
4563 return old_bank != *cur_bank;
4566 } else if (PCI(pc)->op == POC_BANKSEL) {
4567 int old_bank = *cur_bank;
4568 regs *r = PCOR(PCI(pc)->pcop)->r;
4569 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4570 LastRegIdx = reg->rIdx;
4571 return old_bank != *cur_bank;
4577 /*-----------------------------------------------------------------*/
4578 /* Set bank selection if necessary */
4579 /*-----------------------------------------------------------------*/
4580 static int DoBankSelect(pCode *pc, int cur_bank) {
4588 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4589 if (pcf && isPCF(pcf)) {
4591 int rbank = 'U'; // Undetermined
4592 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4593 // Check all the returns to work out what bank is selected
4594 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4596 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4598 rbank = PCFL(pcfr)->lastBank;
4600 if (rbank != PCFL(pcfr)->lastBank)
4601 return -1; // Unknown bank - multiple returns with different banks
4606 return -1; // Unknown bank
4608 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4609 /* Extern functions may use registers in different bank - must call banksel */
4610 return -1; /* Unknown bank */
4614 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4615 return -1; /* New bank unknown - linkers choice. */
4618 reg = getRegFromInstruction(pc);
4620 if (IsBankChange(pc,reg,&cur_bank))
4622 if (!isPCI_LIT(pc)) {
4624 /* Examine the instruction before this one to make sure it is
4625 * not a skip type instruction */
4626 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4628 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4629 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4631 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4633 if (!PCI(pc)->pcflow)
4634 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4636 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4642 /*-----------------------------------------------------------------*/
4643 /*-----------------------------------------------------------------*/
4645 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4653 pc = findNextInstruction(pcfl->pc.next);
4655 while(isPCinFlow(pc,PCODE(pcfl))) {
4657 cur_bank = DoBankSelect(pc,cur_bank);
4659 pc = findNextInstruction(pc->next);
4663 if(pcprev && cur_bank) {
4664 // Set bank state to unknown at the end of each flow block
4670 /*-----------------------------------------------------------------*/
4671 /*int compareBankFlow - compare the banking requirements between */
4673 /*-----------------------------------------------------------------*/
4675 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4678 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4681 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4684 if(pcflow->firstBank == -1)
4688 if(pcflowLink->pcflow->firstBank == -1) {
4689 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4690 pcflowLink->pcflow->to :
4691 pcflowLink->pcflow->from);
4692 return compareBankFlow(pcflow, pctl, toORfrom);
4696 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4699 pcflowLink->bank_conflict++;
4700 pcflowLink->pcflow->FromConflicts++;
4701 pcflow->ToConflicts++;
4704 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4707 pcflowLink->bank_conflict++;
4708 pcflowLink->pcflow->ToConflicts++;
4709 pcflow->FromConflicts++;
4713 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4714 pcflowLink->pcflow->pc.seq,
4715 pcflowLink->pcflow->FromConflicts,
4716 pcflowLink->pcflow->ToConflicts);
4722 /*-----------------------------------------------------------------*/
4723 /*-----------------------------------------------------------------*/
4725 void FixBankFlow(pBlock *pb)
4729 pCodeFlowLink *pcfl;
4731 pCode *pcflow_max_To=NULL;
4732 pCode *pcflow_max_From=NULL;
4733 int max_ToConflicts=0;
4734 int max_FromConflicts=0;
4736 /fprintf(stderr,"Fix Bank flow \n");
4737 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4741 First loop through all of the flow objects in this pcode block
4742 and fix the ones that have banking conflicts between the
4746 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4748 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4750 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4752 if(!isPCFL(pcflow)) {
4753 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4757 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4758 PCFL(pcflow)->firstBank >= 0 &&
4759 PCFL(pcflow)->lastBank >= 0 ) {
4761 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4762 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4764 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4765 BanksUsedFlow2(pcflow);
4770 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4772 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4774 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4779 if(!isPCFL(pcflow)) {
4780 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4784 PCFL(pcflow)->FromConflicts = 0;
4785 PCFL(pcflow)->ToConflicts = 0;
4790 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4791 pcfl = setFirstItem(PCFL(pcflow)->from);
4794 pc = PCODE(pcfl->pcflow);
4797 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4798 pc->print(stderr,pc);
4801 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4804 pcfl=setNextItem(PCFL(pcflow)->from);
4807 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4808 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4810 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4811 BanksUsedFlow2(pcflow);
4813 continue; / * Don't need to check the flow from here - it's already been fixed * /
4820 pcfl = setFirstItem(PCFL(pcflow)->to);
4823 pc = PCODE(pcfl->pcflow);
4825 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4826 pc->print(stderr,pc);
4829 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4832 pcfl=setNextItem(PCFL(pcflow)->to);
4835 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4836 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4838 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4839 BanksUsedFlow2(pcflow);
4844 Loop through the flow objects again and find the ones with the
4848 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4850 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4852 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4853 pcflow_max_To = pcflow;
4855 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4856 pcflow_max_From = pcflow;
4860 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4861 PCFL(pcflow_max_To)->pc.seq,
4862 PCFL(pcflow_max_To)->ToConflicts);
4865 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4866 PCFL(pcflow_max_From)->pc.seq,
4867 PCFL(pcflow_max_From)->FromConflicts);
4872 /*-----------------------------------------------------------------*/
4873 /*-----------------------------------------------------------------*/
4874 void DumpFlow(pBlock *pb)
4878 pCodeFlowLink *pcfl;
4881 fprintf(stderr,"Dump flow \n");
4882 pb->pcHead->print(stderr, pb->pcHead);
4884 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4885 pcflow->print(stderr,pcflow);
4887 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4889 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4891 if(!isPCFL(pcflow)) {
4892 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4895 fprintf(stderr,"dumping: ");
4896 pcflow->print(stderr,pcflow);
4897 FlowStats(PCFL(pcflow));
4899 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4901 pc = PCODE(pcfl->pcflow);
4903 fprintf(stderr, " from seq %d:\n",pc->seq);
4905 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4906 pc->print(stderr,pc);
4911 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4913 pc = PCODE(pcfl->pcflow);
4915 fprintf(stderr, " to seq %d:\n",pc->seq);
4917 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4918 pc->print(stderr,pc);
4927 /*-----------------------------------------------------------------*/
4928 /*-----------------------------------------------------------------*/
4929 int OptimizepBlock(pBlock *pb)
4934 if(!pb || !peepOptimizing)
4937 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4939 for(pc = pb->pcHead; pc; pc = pc->next)
4940 matches += pCodePeepMatchRule(pc);
4943 pc = findNextInstruction(pb->pcHead);
4951 if(pCodePeepMatchRule(pc)) {
4956 pc = findNextInstruction(pcprev->next);
4958 pc = findNextInstruction(pb->pcHead);
4960 pc = findNextInstruction(pc->next);
4964 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4969 /*-----------------------------------------------------------------*/
4970 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4971 /*-----------------------------------------------------------------*/
4972 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4976 for(pc = pcs; pc; pc = pc->next) {
4978 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4980 (PCI(pc)->pcop->type == PO_LABEL) &&
4981 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4988 /*-----------------------------------------------------------------*/
4989 /*-----------------------------------------------------------------*/
4990 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4997 (PCI(pc)->pcop->type == PO_LABEL)) {
4999 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5001 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5003 free(pcol->pcop.name);
5005 /* If the key is negative, then we (probably) have a label to
5006 * a function and the name is already defined */
5009 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5013 //sprintf(buffer,"_%05d_DS_",pcl->key);
5015 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5017 pcol->pcop.name = Safe_strdup(s);
5018 pcol->key = pcl->key;
5019 //pc->print(stderr,pc);
5026 /*-----------------------------------------------------------------*/
5027 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5028 /* pCode chain if they're not used. */
5029 /*-----------------------------------------------------------------*/
5030 void pBlockRemoveUnusedLabels(pBlock *pb)
5032 pCode *pc; pCodeLabel *pcl;
5037 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5039 pBranch *pbr = PCI(pc)->label;
5040 if(pbr && pbr->next) {
5041 pCode *pcd = pb->pcHead;
5043 //fprintf(stderr, "multiple labels\n");
5044 //pc->print(stderr,pc);
5049 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5050 //fprintf(stderr,"Used by:\n");
5051 //pcd->print(stderr,pcd);
5053 exchangeLabels(PCL(pbr->pc),pcd);
5062 for(pc = pb->pcHead; pc; pc = pc->next) {
5064 if(isPCL(pc)) // Label pcode
5066 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5067 pcl = PCL(PCI(pc)->label->pc);
5070 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5072 /* This pCode is a label, so search the pBlock to see if anyone
5075 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5076 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5077 /* Couldn't find an instruction that refers to this label
5078 * So, unlink the pCode label from it's pCode chain
5079 * and destroy the label */
5080 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5082 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5083 if(pc->type == PC_LABEL) {
5085 pCodeLabelDestruct(pc);
5087 unlinkpCodeFromBranch(pc, PCODE(pcl));
5088 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5099 /*-----------------------------------------------------------------*/
5100 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5101 /* chain and put them into pBranches that are */
5102 /* associated with the appropriate pCode */
5104 /*-----------------------------------------------------------------*/
5105 void pBlockMergeLabels(pBlock *pb)
5108 pCode *pc, *pcnext=NULL;
5113 /* First, Try to remove any unused labels */
5114 //pBlockRemoveUnusedLabels(pb);
5116 /* Now loop through the pBlock and merge the labels with the opcodes */
5119 // for(pc = pb->pcHead; pc; pc = pc->next) {
5122 pCode *pcn = pc->next;
5124 if(pc->type == PC_LABEL) {
5126 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5127 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5128 if((pcnext = findNextInstruction(pc) )) {
5130 // Unlink the pCode label from it's pCode chain
5133 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5134 // And link it into the instruction's pBranch labels. (Note, since
5135 // it's possible to have multiple labels associated with one instruction
5136 // we must provide a means to accomodate the additional labels. Thus
5137 // the labels are placed into the singly-linked list "label" as
5138 // opposed to being a single member of the pCodeInstruction.)
5140 //_ALLOC(pbr,sizeof(pBranch));
5141 pbr = Safe_calloc(1,sizeof(pBranch));
5145 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5148 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5150 } else if(pc->type == PC_CSOURCE) {
5152 /* merge the source line symbolic info into the next instruction */
5153 if((pcnext = findNextInstruction(pc) )) {
5155 // Unlink the pCode label from it's pCode chain
5157 PCI(pcnext)->cline = PCCS(pc);
5158 //fprintf(stderr, "merging CSRC\n");
5159 //genericPrint(stderr,pcnext);
5165 pBlockRemoveUnusedLabels(pb);
5169 /*-----------------------------------------------------------------*/
5170 /*-----------------------------------------------------------------*/
5171 int OptimizepCode(char dbName)
5173 #define MAX_PASSES 4
5182 DFPRINTF((stderr," Optimizing pCode\n"));
5186 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5187 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5188 matches += OptimizepBlock(pb);
5191 while(matches && ++passes < MAX_PASSES);
5196 /*-----------------------------------------------------------------*/
5197 /* popCopyGPR2Bit - copy a pcode operator */
5198 /*-----------------------------------------------------------------*/
5200 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5204 pcop = newpCodeOpBit(pc->name, bitval, 0);
5206 if( !( (pcop->type == PO_LABEL) ||
5207 (pcop->type == PO_LITERAL) ||
5208 (pcop->type == PO_STR) ))
5209 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5215 /*-----------------------------------------------------------------*/
5216 /*-----------------------------------------------------------------*/
5217 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5220 int firstBank = 'U';
5225 for (pc=pb->pcHead; pc; pc=pc->next) {
5227 firstBank = PCFL(pc)->firstBank;
5231 if (firstBank != 'U') {
5232 /* This block has already been done */
5233 if (firstBank != cur_bank) {
5234 /* This block has started with a different bank - must adjust it */
5235 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5238 regs *reg = getRegFromInstruction(pc);
5240 DoBankSelect(pc,cur_bank);
5250 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5253 for (pc=pb->pcHead; pc; pc=pc->next) {
5255 PCFL(pc)->firstBank = cur_bank;
5258 cur_bank = DoBankSelect(pc,cur_bank);
5261 /* Trace through branches and set the bank selection as required. */
5264 for (pc=pb->pcHead; pc; pc=pc->next) {
5266 PCFL(pc)->firstBank = cur_bank;
5270 if (PCI(pc)->op == POC_GOTO) {
5271 int lastRegIdx = LastRegIdx;
5273 /* Trace through branch */
5274 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5277 regs *reg = getRegFromInstruction(pcl);
5279 int bankUnknown = -1;
5280 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5282 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5288 LastRegIdx = lastRegIdx;
5290 /* Keep track out current bank */
5291 regs *reg = getRegFromInstruction(pc);
5293 IsBankChange(pc,reg,&cur_bank);
5300 /*-----------------------------------------------------------------*/
5301 /*-----------------------------------------------------------------*/
5302 void pBlockDestruct(pBlock *pb)
5313 /*-----------------------------------------------------------------*/
5314 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5315 /* name dbName and combine them */
5316 /* into one block */
5317 /*-----------------------------------------------------------------*/
5318 void mergepBlocks(char dbName)
5321 pBlock *pb, *pbmerged = NULL,*pbn;
5323 pb = the_pFile->pbHead;
5325 //fprintf(stderr," merging blocks named %c\n",dbName);
5329 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5330 if( getpBlock_dbName(pb) == dbName) {
5332 //fprintf(stderr," merged block %c\n",dbName);
5337 addpCode2pBlock(pbmerged, pb->pcHead);
5338 /* addpCode2pBlock doesn't handle the tail: */
5339 pbmerged->pcTail = pb->pcTail;
5341 pb->prev->next = pbn;
5343 pbn->prev = pb->prev;
5348 //printpBlock(stderr, pbmerged);
5355 /*-----------------------------------------------------------------*/
5356 /* AnalyzeFlow - Examine the flow of the code and optimize */
5358 /* level 0 == minimal optimization */
5359 /* optimize registers that are used only by two instructions */
5360 /* level 1 == maximal optimization */
5361 /* optimize by looking at pairs of instructions that use the */
5363 /*-----------------------------------------------------------------*/
5365 void AnalyzeFlow(int level)
5367 static int times_called=0;
5375 /* if this is not the first time this function has been called,
5376 then clean up old flow information */
5377 if(times_called++) {
5378 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5381 RegsUnMapLiveRanges();
5387 /* Phase 2 - Flow Analysis - Register Banking
5389 * In this phase, the individual flow blocks are examined
5390 * and register banking is fixed.
5393 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5394 //FixRegisterBanking(pb);
5396 /* Phase 2 - Flow Analysis
5398 * In this phase, the pCode is partition into pCodeFlow
5399 * blocks. The flow blocks mark the points where a continuous
5400 * stream of instructions changes flow (e.g. because of
5401 * a call or goto or whatever).
5404 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5408 /* Phase 2 - Flow Analysis - linking flow blocks
5410 * In this phase, the individual flow blocks are examined
5411 * to determine their order of excution.
5414 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5417 /* Phase 3 - Flow Analysis - Flow Tree
5419 * In this phase, the individual flow blocks are examined
5420 * to determine their order of excution.
5423 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5427 /* Phase x - Flow Analysis - Used Banks
5429 * In this phase, the individual flow blocks are examined
5430 * to determine the Register Banks they use
5433 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5437 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5438 pCodeRegMapLiveRanges(pb);
5440 RemoveUnusedRegisters();
5442 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5443 pCodeRegOptimizeRegUsage(level);
5449 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5454 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5456 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5457 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5458 pcflow = pcflow->next) {
5460 FillFlow(PCFL(pcflow));
5465 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5467 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5468 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5469 pcflow = pcflow->next) {
5471 FlowStats(PCFL(pcflow));
5477 /*-----------------------------------------------------------------*/
5478 /* AnalyzeBanking - Called after the memory addresses have been */
5479 /* assigned to the registers. */
5481 /*-----------------------------------------------------------------*/
5483 void AnalyzeBanking(void)
5487 if(!picIsInitialized()) {
5488 setDefMaxRam(); // Max RAM has not been included, so use default setting
5491 /* Phase x - Flow Analysis - Used Banks
5493 * In this phase, the individual flow blocks are examined
5494 * to determine the Register Banks they use
5500 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5501 // BanksUsedFlow(pb);
5502 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5503 FixRegisterBanking(pb,-1); // cur_bank is unknown
5507 /*-----------------------------------------------------------------*/
5508 /*-----------------------------------------------------------------*/
5509 DEFSETFUNC (resetrIdx)
5511 regs *r = (regs *)item;
5519 /*-----------------------------------------------------------------*/
5520 /* InitRegReuse - Initialises variables for code analyzer */
5521 /*-----------------------------------------------------------------*/
5523 void InitReuseReg(void)
5525 /* Find end of statically allocated variables for start idx */
5526 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5528 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5529 if (r->type != REG_SFR) {
5530 maxIdx += r->size; /* Increment for all statically allocated variables */
5534 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5537 /*-----------------------------------------------------------------*/
5538 /*-----------------------------------------------------------------*/
5539 static unsigned register_reassign(pBlock *pb, unsigned idx)
5543 /* check recursion */
5544 pc = setFirstItem(pb->function_entries);
5550 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5552 if (pb->tregisters) {
5554 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5555 if (r->type == REG_GPR) {
5557 if (r->rIdx < (int)idx) {
5560 if (peakIdx < idx) peakIdx = idx;
5561 sprintf(s,"r0x%02X", r->rIdx);
5562 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5564 r->name = Safe_strdup(s);
5570 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5572 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5573 char *dest = get_op_from_instruction(PCI(pc));
5575 pCode *pcn = findFunction(dest);
5577 register_reassign(pcn->pb,idx);
5586 /*------------------------------------------------------------------*/
5587 /* ReuseReg were call tree permits */
5589 /* Re-allocate the GPR for optimum reuse for a given pblock */
5590 /* eg if a function m() calls function f1() and f2(), where f1 */
5591 /* allocates a local variable vf1 and f2 allocates a local */
5592 /* variable vf2. Then providing f1 and f2 do not call each other */
5593 /* they may share the same general purpose registers for vf1 and */
5595 /* This is done by first setting the the regs rIdx to start after */
5596 /* all the global variables, then walking through the call tree */
5597 /* renaming the registers to match their new idx and incrementng */
5598 /* it as it goes. If a function has already been called it will */
5599 /* only rename the registers if it has already used up those */
5600 /* registers ie rIdx of the function's registers is lower than the */
5601 /* current rIdx. That way the register will not be reused while */
5602 /* still being used by an eariler function call. */
5604 /* Note for this to work the functions need to be declared static. */
5606 /*------------------------------------------------------------------*/
5611 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5612 /* Non static functions can be called from other modules so their registers must reassign */
5613 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5614 register_reassign(pb,peakIdx);
5618 /*-----------------------------------------------------------------*/
5619 /* buildCallTree - look at the flow and extract all of the calls */
5621 /*-----------------------------------------------------------------*/
5623 void buildCallTree(void )
5632 /* Now build the call tree.
5633 First we examine all of the pCodes for functions.
5634 Keep in mind that the function boundaries coincide
5635 with pBlock boundaries.
5637 The algorithm goes something like this:
5638 We have two nested loops. The outer loop iterates
5639 through all of the pBlocks/functions. The inner
5640 loop iterates through all of the pCodes for
5641 a given pBlock. When we begin iterating through
5642 a pBlock, the variable pc_fstart, pCode of the start
5643 of a function, is cleared. We then search for pCodes
5644 of type PC_FUNCTION. When one is encountered, we
5645 initialize pc_fstart to this and at the same time
5646 associate a new pBranch object that signifies a
5647 branch entry. If a return is found, then this signifies
5648 a function exit point. We'll link the pCodes of these
5649 returns to the matching pc_fstart.
5651 When we're done, a doubly linked list of pBranches
5652 will exist. The head of this list is stored in
5653 `the_pFile', which is the meta structure for all
5654 of the pCode. Look at the printCallTree function
5655 on how the pBranches are linked together.
5658 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5659 pCode *pc_fstart=NULL;
5660 for(pc = pb->pcHead; pc; pc = pc->next) {
5662 pCodeFunction *pcf = PCF(pc);
5665 if(STRCASECMP(pcf->fname, "_main") == 0) {
5666 //fprintf(stderr," found main \n");
5667 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5671 pbr = Safe_calloc(1,sizeof(pBranch));
5672 pbr->pc = pc_fstart = pc;
5675 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5677 // Here's a better way of doing the same:
5678 addSet(&pb->function_entries, pc);
5681 // Found an exit point in a function, e.g. return
5682 // (Note, there may be more than one return per function)
5684 pBranchLink(PCF(pc_fstart), pcf);
5686 addSet(&pb->function_exits, pc);
5688 } else if(isCALL(pc)) {
5689 addSet(&pb->function_calls,pc);
5695 /*-----------------------------------------------------------------*/
5696 /* AnalyzepCode - parse the pCode that has been generated and form */
5697 /* all of the logical connections. */
5699 /* Essentially what's done here is that the pCode flow is */
5701 /*-----------------------------------------------------------------*/
5703 void AnalyzepCode(char dbName)
5714 /* Phase 1 - Register allocation and peep hole optimization
5716 * The first part of the analysis is to determine the registers
5717 * that are used in the pCode. Once that is done, the peep rules
5718 * are applied to the code. We continue to loop until no more
5719 * peep rule optimizations are found (or until we exceed the
5720 * MAX_PASSES threshold).
5722 * When done, the required registers will be determined.
5728 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5730 /* First, merge the labels with the instructions */
5731 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5732 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5734 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5735 pBlockMergeLabels(pb);
5738 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5742 changes = OptimizepCode(dbName);
5744 } while(changes && (i++ < MAX_PASSES));
5749 /*-----------------------------------------------------------------*/
5750 /* ispCodeFunction - returns true if *pc is the pCode of a */
5752 /*-----------------------------------------------------------------*/
5753 bool ispCodeFunction(pCode *pc)
5756 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5762 /*-----------------------------------------------------------------*/
5763 /* findFunction - Search for a function by name (given the name) */
5764 /* in the set of all functions that are in a pBlock */
5765 /* (note - I expect this to change because I'm planning to limit */
5766 /* pBlock's to just one function declaration */
5767 /*-----------------------------------------------------------------*/
5768 pCode *findFunction(char *fname)
5775 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5777 pc = setFirstItem(pb->function_entries);
5780 if((pc->type == PC_FUNCTION) &&
5782 (strcmp(fname, PCF(pc)->fname)==0))
5785 pc = setNextItem(pb->function_entries);
5793 void MarkUsedRegisters(set *regset)
5798 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5799 r2 = pic14_regWithIdx(r1->rIdx);
5807 void pBlockStats(FILE *of, pBlock *pb)
5813 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5815 // for now just print the first element of each set
5816 pc = setFirstItem(pb->function_entries);
5818 fprintf(of,";entry: ");
5821 pc = setFirstItem(pb->function_exits);
5823 fprintf(of,";has an exit\n");
5827 pc = setFirstItem(pb->function_calls);
5829 fprintf(of,";functions called:\n");
5832 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5833 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5835 pc = setNextItem(pb->function_calls);
5839 r = setFirstItem(pb->tregisters);
5841 int n = elementsInSet(pb->tregisters);
5843 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5846 fprintf(of,"; %s\n",r->name);
5847 r = setNextItem(pb->tregisters);
5852 /*-----------------------------------------------------------------*/
5853 /*-----------------------------------------------------------------*/
5855 static void sequencepCode(void)
5861 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5863 pb->seq = GpCodeSequenceNumber+1;
5865 for( pc = pb->pcHead; pc; pc = pc->next)
5866 pc->seq = ++GpCodeSequenceNumber;
5872 /*-----------------------------------------------------------------*/
5873 /*-----------------------------------------------------------------*/
5875 set *register_usage(pBlock *pb)
5878 set *registers=NULL;
5879 set *registersInCallPath = NULL;
5881 / * check recursion * /
5883 pc = setFirstItem(pb->function_entries);
5890 if(pc->type != PC_FUNCTION)
5891 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5893 pc = setFirstItem(pb->function_calls);
5894 for( ; pc; pc = setNextItem(pb->function_calls)) {
5896 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5897 char *dest = get_op_from_instruction(PCI(pc));
5899 pcn = findFunction(dest);
5901 registersInCallPath = register_usage(pcn->pb);
5903 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5908 pBlockStats(stderr,pb); // debug
5911 // Mark the registers in this block as used.
5913 MarkUsedRegisters(pb->tregisters);
5914 if(registersInCallPath) {
5915 / * registers were used in the functions this pBlock has called * /
5916 / * so now, we need to see if these collide with the ones we are * /
5919 regs *r1,*r2, *newreg;
5921 DFPRINTF((stderr,"comparing registers\n"));
5923 r1 = setFirstItem(registersInCallPath);
5925 if (r1->type != REG_STK) {
5926 r2 = setFirstItem(pb->tregisters);
5928 while(r2 && (r2->type != REG_STK)) {
5930 if(r2->rIdx == r1->rIdx) {
5931 newreg = pic14_findFreeReg(REG_GPR);
5935 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5939 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5940 r1->rIdx, newreg->rIdx));
5941 r2->rIdx = newreg->rIdx;
5943 r2->name = Safe_strdup(newreg->name);
5947 newreg->wasUsed = 1;
5949 r2 = setNextItem(pb->tregisters);
5953 r1 = setNextItem(registersInCallPath);
5956 / * Collisions have been resolved. Now free the registers in the call path * /
5957 r1 = setFirstItem(registersInCallPath);
5959 newreg = pic14_regWithIdx(r1->rIdx);
5960 if (newreg) newreg->isFree = 1;
5961 r1 = setNextItem(registersInCallPath);
5965 // MarkUsedRegisters(pb->registers);
5967 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5970 DFPRINTF((stderr,"returning regs\n"));
5972 DFPRINTF((stderr,"not returning regs\n"));
5974 DFPRINTF((stderr,"pBlock after register optim.\n"));
5975 pBlockStats(stderr,pb); // debug
5982 /*-----------------------------------------------------------------*/
5983 /* printCallTree - writes the call tree to a file */
5985 /*-----------------------------------------------------------------*/
5986 void pct2(FILE *of,pBlock *pb,int indent)
5990 // set *registersInCallPath = NULL;
5996 return; //recursion ?
5998 pc = setFirstItem(pb->function_entries);
6005 for(i=0;i<indent;i++) // Indentation
6008 if(pc->type == PC_FUNCTION)
6009 fprintf(of,"%s\n",PCF(pc)->fname);
6014 pc = setFirstItem(pb->function_calls);
6015 for( ; pc; pc = setNextItem(pb->function_calls)) {
6017 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6018 char *dest = get_op_from_instruction(PCI(pc));
6020 pcn = findFunction(dest);
6022 pct2(of,pcn->pb,indent+1);
6024 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6032 /*-----------------------------------------------------------------*/
6033 /* printCallTree - writes the call tree to a file */
6035 /*-----------------------------------------------------------------*/
6037 void printCallTree(FILE *of)
6049 fprintf(of, "\npBlock statistics\n");
6050 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6055 fprintf(of,"Call Tree\n");
6056 pbr = the_pFile->functions;
6060 if(!ispCodeFunction(pc))
6061 fprintf(of,"bug in call tree");
6064 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6066 while(pc->next && !ispCodeFunction(pc->next)) {
6068 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6069 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6077 fprintf(of,"\n**************\n\na better call tree\n");
6078 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6083 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6084 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6090 /*-----------------------------------------------------------------*/
6092 /*-----------------------------------------------------------------*/
6094 void InlineFunction(pBlock *pb)
6102 pc = setFirstItem(pb->function_calls);
6104 for( ; pc; pc = setNextItem(pb->function_calls)) {
6107 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6108 pCode *pcp = pc->prev;
6114 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 */
6116 InlineFunction(pcn->pb);
6119 At this point, *pc points to a CALL mnemonic, and
6120 *pcn points to the function that is being called.
6122 To in-line this call, we need to remove the CALL
6123 and RETURN(s), and link the function pCode in with
6130 /* Check if previous instruction was a bit skip */
6131 if (isPCI_BITSKIP(pcp)) {
6133 /* Invert skip instruction and add a goto */
6134 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6136 if(isPCL(pc_call->next)) { // Label pcode
6137 pcl = PCL(pc_call->next);
6138 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6139 pcl = PCL(PCI(pc_call->next)->label->pc);
6141 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6142 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6144 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6147 /* remove callee pBlock from the pBlock linked list */
6148 removepBlock(pcn->pb);
6156 /* Remove the Function pCode */
6157 pct = findNextInstruction(pcn->next);
6159 /* Link the function with the callee */
6160 if (pcp) pcp->next = pcn->next;
6161 pcn->next->prev = pcp;
6163 /* Convert the function name into a label */
6165 pbr = Safe_calloc(1,sizeof(pBranch));
6166 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6168 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6169 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6171 /* turn all of the return's except the last into goto's */
6172 /* check case for 2 instruction pBlocks */
6173 pce = findNextInstruction(pcn->next);
6175 pCode *pce_next = findNextInstruction(pce->next);
6177 if(pce_next == NULL) {
6178 /* found the last return */
6179 pCode *pc_call_next = findNextInstruction(pc_call->next);
6181 //fprintf(stderr,"found last return\n");
6182 //pce->print(stderr,pce);
6183 pce->prev->next = pc_call->next;
6184 pc_call->next->prev = pce->prev;
6185 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6194 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6200 /*-----------------------------------------------------------------*/
6202 /*-----------------------------------------------------------------*/
6204 void InlinepCode(void)
6213 if(!functionInlining)
6216 /* Loop through all of the function definitions and count the
6217 * number of times each one is called */
6218 //fprintf(stderr,"inlining %d\n",__LINE__);
6220 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6222 pc = setFirstItem(pb->function_calls);
6224 for( ; pc; pc = setNextItem(pb->function_calls)) {
6227 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6228 if(pcn && isPCF(pcn)) {
6229 PCF(pcn)->ncalled++;
6232 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6237 //fprintf(stderr,"inlining %d\n",__LINE__);
6239 /* Now, Loop through the function definitions again, but this
6240 * time inline those functions that have only been called once. */
6242 InlineFunction(the_pFile->pbHead);
6243 //fprintf(stderr,"inlining %d\n",__LINE__);
6245 for(pb = the_pFile->pbHead; pb; pb = pb->next)