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;
1258 if (pcodeId == 1448)
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 init_pic(port->processor);
1347 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1348 if ((unsigned)shareBankAddress > getMaxRam()) /* If total RAM is less than 0x7f as with 16f84 then reduce shareBankAddress to fit */
1349 shareBankAddress = (int)getMaxRam();
1350 stkSize = 15; /* Set pseudo stack size to 15, on multi memory bank ICs this leaves room for WSAVE (used for interrupts) to fit into the shared portion of the memory bank */
1351 initStack(shareBankAddress, stkSize); /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1353 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1354 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1355 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1356 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1357 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1358 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1360 pc_status.rIdx = IDX_STATUS;
1361 pc_fsr.rIdx = IDX_FSR;
1362 pc_indf.rIdx = IDX_INDF;
1363 pc_intcon.rIdx = IDX_INTCON;
1364 pc_pcl.rIdx = IDX_PCL;
1365 pc_pclath.rIdx = IDX_PCLATH;
1367 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1368 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1369 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1371 pc_wsave.rIdx = pc_wsave.r->rIdx;
1372 pc_ssave.rIdx = pc_ssave.r->rIdx;
1373 pc_psave.rIdx = pc_psave.r->rIdx;
1375 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1376 pc_wsave.r->address = shareBankAddress-stkSize;
1377 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1378 pc_ssave.r->address = shareBankAddress-stkSize-1;
1379 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1380 pc_psave.r->address = shareBankAddress-stkSize-2;
1382 /* probably should put this in a separate initialization routine */
1383 pb_dead_pcodes = newpBlock();
1387 /*-----------------------------------------------------------------*/
1388 /* mnem2key - convert a pic mnemonic into a hash key */
1389 /* (BTW - this spreads the mnemonics quite well) */
1391 /*-----------------------------------------------------------------*/
1393 int mnem2key(char const *mnem)
1402 key += toupper(*mnem++) +1;
1406 return (key & 0x1f);
1410 void pic14initMnemonics(void)
1415 pCodeInstruction *pci;
1417 if(mnemonics_initialized)
1420 //FIXME - probably should NULL out the array before making the assignments
1421 //since we check the array contents below this initialization.
1423 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1424 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1425 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1426 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1427 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1428 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1429 pic14Mnemonics[POC_BCF] = &pciBCF;
1430 pic14Mnemonics[POC_BSF] = &pciBSF;
1431 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1432 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1433 pic14Mnemonics[POC_CALL] = &pciCALL;
1434 pic14Mnemonics[POC_COMF] = &pciCOMF;
1435 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1436 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1437 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1438 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1439 pic14Mnemonics[POC_DECF] = &pciDECF;
1440 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1441 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1442 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1443 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1444 pic14Mnemonics[POC_INCF] = &pciINCF;
1445 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1446 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1447 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1448 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1449 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1450 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1451 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1452 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1453 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1454 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1455 pic14Mnemonics[POC_NOP] = &pciNOP;
1456 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1457 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1458 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1459 pic14Mnemonics[POC_RLF] = &pciRLF;
1460 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1461 pic14Mnemonics[POC_RRF] = &pciRRF;
1462 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1463 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1464 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1465 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1466 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1467 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1468 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1469 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1470 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1471 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1472 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1473 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1475 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1476 if(pic14Mnemonics[i])
1477 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1478 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1481 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1482 pci = hTabNextItem(pic14MnemonicsHash, &key);
1485 mnemonics_initialized = 1;
1488 int getpCodePeepCommand(char *cmd);
1490 int getpCode(char *mnem,unsigned dest)
1493 pCodeInstruction *pci;
1494 int key = mnem2key(mnem);
1496 if(!mnemonics_initialized)
1497 pic14initMnemonics();
1499 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1503 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1504 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1508 pci = hTabNextItemWK (pic14MnemonicsHash);
1515 /*-----------------------------------------------------------------*
1516 * pic14initpCodePeepCommands
1518 *-----------------------------------------------------------------*/
1519 void pic14initpCodePeepCommands(void)
1527 hTabAddItem(&pic14pCodePeepCommandsHash,
1528 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1530 } while (peepCommands[i].cmd);
1532 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1535 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1536 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1541 /*-----------------------------------------------------------------
1544 *-----------------------------------------------------------------*/
1546 int getpCodePeepCommand(char *cmd)
1550 int key = mnem2key(cmd);
1553 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1556 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1557 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1561 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1568 char getpBlock_dbName(pBlock *pb)
1574 return pb->cmemmap->dbName;
1578 void pBlockConvert2ISR(pBlock *pb)
1589 /*-----------------------------------------------------------------*/
1590 /* movepBlock2Head - given the dbname of a pBlock, move all */
1591 /* instances to the front of the doubly linked */
1592 /* list of pBlocks */
1593 /*-----------------------------------------------------------------*/
1595 void movepBlock2Head(char dbName)
1602 pb = the_pFile->pbHead;
1606 if(getpBlock_dbName(pb) == dbName) {
1607 pBlock *pbn = pb->next;
1608 pb->next = the_pFile->pbHead;
1609 the_pFile->pbHead->prev = pb;
1610 the_pFile->pbHead = pb;
1613 pb->prev->next = pbn;
1615 // If the pBlock that we just moved was the last
1616 // one in the link of all of the pBlocks, then we
1617 // need to point the tail to the block just before
1618 // the one we moved.
1619 // Note: if pb->next is NULL, then pb must have
1620 // been the last pBlock in the chain.
1623 pbn->prev = pb->prev;
1625 the_pFile->pbTail = pb->prev;
1636 void copypCode(FILE *of, char dbName)
1640 if(!of || !the_pFile)
1643 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1644 if(getpBlock_dbName(pb) == dbName) {
1652 void pcode_test(void)
1655 DFPRINTF((stderr,"pcode is alive!\n"));
1665 /* create the file name */
1666 strcpy(buffer,dstFileName);
1667 strcat(buffer,".p");
1669 if( !(pFile = fopen(buffer, "w" ))) {
1670 werror(E_FILE_OPEN_ERR,buffer);
1674 fprintf(pFile,"pcode dump\n\n");
1676 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1677 fprintf(pFile,"\n\tNew pBlock\n\n");
1679 fprintf(pFile,"%s",pb->cmemmap->sname);
1681 fprintf(pFile,"internal pblock");
1683 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1684 printpBlock(pFile,pb);
1688 /*-----------------------------------------------------------------*/
1689 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1690 /* ister, RegCond will return the bit being referenced. */
1692 /* fixme - why not just OR in the pcop bit field */
1693 /*-----------------------------------------------------------------*/
1695 static int RegCond(pCodeOp *pcop)
1701 if (pcop->type == PO_GPR_BIT) {
1702 char *name = pcop->name;
1704 name = PCOR(pcop)->r->name;
1705 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1706 switch(PCORB(pcop)->bit) {
1720 /*-----------------------------------------------------------------*/
1721 /* newpCode - create and return a newly initialized pCode */
1723 /* fixme - rename this */
1725 /* The purpose of this routine is to create a new Instruction */
1726 /* pCode. This is called by gen.c while the assembly code is being */
1730 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1731 /* (note that the op is analogous to but not the */
1732 /* same thing as the opcode of the instruction.) */
1733 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1736 /* a pointer to the new malloc'd pCode is returned. */
1740 /*-----------------------------------------------------------------*/
1741 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1743 pCodeInstruction *pci ;
1745 if(!mnemonics_initialized)
1746 pic14initMnemonics();
1748 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1750 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1751 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1752 pci->pc.id = PCodeID();
1755 if(pci->inCond & PCC_EXAMINE_PCOP)
1756 pci->inCond |= RegCond(pcop);
1758 if(pci->outCond & PCC_EXAMINE_PCOP)
1759 pci->outCond |= RegCond(pcop);
1761 pci->pc.prev = pci->pc.next = NULL;
1762 return (pCode *)pci;
1765 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1771 /*-----------------------------------------------------------------*/
1772 /* newpCodeWild - create a "wild" as in wild card pCode */
1774 /* Wild pcodes are used during the peep hole optimizer to serve */
1775 /* as place holders for any instruction. When a snippet of code is */
1776 /* compared to a peep hole rule, the wild card opcode will match */
1777 /* any instruction. However, the optional operand and label are */
1778 /* additional qualifiers that must also be matched before the */
1779 /* line (of assembly code) is declared matched. Note that the */
1780 /* operand may be wild too. */
1782 /* Note, a wild instruction is specified just like a wild var: */
1783 /* %4 ; A wild instruction, */
1784 /* See the peeph.def file for additional examples */
1786 /*-----------------------------------------------------------------*/
1788 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1793 pcw = Safe_calloc(1,sizeof(pCodeWild));
1795 pcw->pci.pc.type = PC_WILD;
1796 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1797 pcw->id = PCodeID();
1798 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1799 pcw->pci.pc.pb = NULL;
1801 // pcw->pci.pc.analyze = genericAnalyze;
1802 pcw->pci.pc.destruct = genericDestruct;
1803 pcw->pci.pc.print = genericPrint;
1805 pcw->id = pCodeID; // this is the 'n' in %n
1806 pcw->operand = optional_operand;
1807 pcw->label = optional_label;
1809 pcw->mustBeBitSkipInst = 0;
1810 pcw->mustNotBeBitSkipInst = 0;
1811 pcw->invertBitSkipInst = 0;
1813 return ( (pCode *)pcw);
1817 /*-----------------------------------------------------------------*/
1818 /* newPcodeInlineP - create a new pCode from a char string */
1819 /*-----------------------------------------------------------------*/
1822 pCode *newpCodeInlineP(char *cP)
1827 pcc = Safe_calloc(1,sizeof(pCodeComment));
1829 pcc->pc.type = PC_INLINE;
1830 pcc->pc.prev = pcc->pc.next = NULL;
1831 pcc->pc.id = PCodeID();
1832 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1835 // pcc->pc.analyze = genericAnalyze;
1836 pcc->pc.destruct = genericDestruct;
1837 pcc->pc.print = genericPrint;
1840 pcc->comment = Safe_strdup(cP);
1842 pcc->comment = NULL;
1844 return ( (pCode *)pcc);
1848 /*-----------------------------------------------------------------*/
1849 /* newPcodeCharP - create a new pCode from a char string */
1850 /*-----------------------------------------------------------------*/
1852 pCode *newpCodeCharP(char *cP)
1857 pcc = Safe_calloc(1,sizeof(pCodeComment));
1859 pcc->pc.type = PC_COMMENT;
1860 pcc->pc.prev = pcc->pc.next = NULL;
1861 pcc->pc.id = PCodeID();
1862 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1865 // pcc->pc.analyze = genericAnalyze;
1866 pcc->pc.destruct = genericDestruct;
1867 pcc->pc.print = genericPrint;
1870 pcc->comment = Safe_strdup(cP);
1872 pcc->comment = NULL;
1874 return ( (pCode *)pcc);
1878 /*-----------------------------------------------------------------*/
1879 /* newpCodeFunction - */
1880 /*-----------------------------------------------------------------*/
1883 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1887 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1888 //_ALLOC(pcf,sizeof(pCodeFunction));
1890 pcf->pc.type = PC_FUNCTION;
1891 pcf->pc.prev = pcf->pc.next = NULL;
1892 pcf->pc.id = PCodeID();
1893 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1896 // pcf->pc.analyze = genericAnalyze;
1897 pcf->pc.destruct = genericDestruct;
1898 pcf->pc.print = pCodePrintFunction;
1903 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1904 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1905 strcpy(pcf->modname,mod);
1907 pcf->modname = NULL;
1910 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1911 pcf->fname = Safe_calloc(1,strlen(f)+1);
1912 strcpy(pcf->fname,f);
1916 pcf->isPublic = (unsigned)isPublic;
1918 return ( (pCode *)pcf);
1922 /*-----------------------------------------------------------------*/
1924 /*-----------------------------------------------------------------*/
1925 void destructpCodeFlow(pCode *pc)
1927 if(!pc || !isPCFL(pc))
1936 deleteSet(&PCFL(pc)->registers);
1937 deleteSet(&PCFL(pc)->from);
1938 deleteSet(&PCFL(pc)->to);
1943 pCode *newpCodeFlow(void )
1947 //_ALLOC(pcflow,sizeof(pCodeFlow));
1948 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1950 pcflow->pc.type = PC_FLOW;
1951 pcflow->pc.prev = pcflow->pc.next = NULL;
1952 pcflow->pc.pb = NULL;
1954 // pcflow->pc.analyze = genericAnalyze;
1955 pcflow->pc.destruct = destructpCodeFlow;
1956 pcflow->pc.print = genericPrint;
1958 pcflow->pc.seq = GpcFlowSeq++;
1960 pcflow->from = pcflow->to = NULL;
1962 pcflow->inCond = PCC_NONE;
1963 pcflow->outCond = PCC_NONE;
1965 pcflow->firstBank = 'U'; /* Undetermined */
1966 pcflow->lastBank = 'U'; /* Undetermined */
1968 pcflow->FromConflicts = 0;
1969 pcflow->ToConflicts = 0;
1973 pcflow->registers = newSet();
1975 return ( (pCode *)pcflow);
1979 /*-----------------------------------------------------------------*/
1980 /*-----------------------------------------------------------------*/
1981 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1983 pCodeFlowLink *pcflowLink;
1985 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1987 pcflowLink->pcflow = pcflow;
1988 pcflowLink->bank_conflict = 0;
1993 /*-----------------------------------------------------------------*/
1994 /* newpCodeCSource - create a new pCode Source Symbol */
1995 /*-----------------------------------------------------------------*/
1997 pCode *newpCodeCSource(int ln, char *f, char *l)
2002 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2004 pccs->pc.type = PC_CSOURCE;
2005 pccs->pc.prev = pccs->pc.next = NULL;
2006 pccs->pc.id = PCodeID();
2009 pccs->pc.destruct = genericDestruct;
2010 pccs->pc.print = genericPrint;
2012 pccs->line_number = ln;
2014 pccs->line = Safe_strdup(l);
2019 pccs->file_name = Safe_strdup(f);
2021 pccs->file_name = NULL;
2023 return ( (pCode *)pccs);
2027 /*******************************************************************/
2028 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2029 /* added by VR 6-Jun-2003 */
2030 /*******************************************************************/
2032 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2039 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2040 pcad->pci.pc.type = PC_ASMDIR;
2041 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2042 pcad->pci.pc.pb = NULL;
2043 pcad->pci.pc.destruct = genericDestruct;
2044 pcad->pci.pc.print = genericPrint;
2046 if(asdir && *asdir) {
2048 while(isspace(*asdir))asdir++; // strip any white space from the beginning
2050 pcad->directive = Safe_strdup( asdir );
2053 va_start(ap, argfmt);
2055 memset(buffer, 0, sizeof(buffer));
2056 if(argfmt && *argfmt)
2057 vsprintf(buffer, argfmt, ap);
2061 while(isspace(*lbp))lbp++;
2064 pcad->arg = Safe_strdup( lbp );
2066 return ((pCode *)pcad);
2069 /*-----------------------------------------------------------------*/
2070 /* pCodeLabelDestruct - free memory used by a label. */
2071 /*-----------------------------------------------------------------*/
2072 static void pCodeLabelDestruct(pCode *pc)
2078 if((pc->type == PC_LABEL) && PCL(pc)->label)
2079 free(PCL(pc)->label);
2085 pCode *newpCodeLabel(char *name, int key)
2091 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2093 pcl->pc.type = PC_LABEL;
2094 pcl->pc.prev = pcl->pc.next = NULL;
2095 pcl->pc.id = PCodeID();
2096 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2099 // pcl->pc.analyze = genericAnalyze;
2100 pcl->pc.destruct = pCodeLabelDestruct;
2101 pcl->pc.print = pCodePrintLabel;
2107 sprintf(s,"_%05d_DS_",key);
2112 pcl->label = Safe_strdup(s);
2114 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2115 return ( (pCode *)pcl);
2120 /*-----------------------------------------------------------------*/
2121 /* newpBlock - create and return a pointer to a new pBlock */
2122 /*-----------------------------------------------------------------*/
2123 pBlock *newpBlock(void)
2128 PpB = Safe_calloc(1,sizeof(pBlock) );
2129 PpB->next = PpB->prev = NULL;
2131 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2132 PpB->tregisters = NULL;
2134 PpB->FlowTree = NULL;
2140 /*-----------------------------------------------------------------*/
2141 /* newpCodeChain - create a new chain of pCodes */
2142 /*-----------------------------------------------------------------*
2144 * This function will create a new pBlock and the pointer to the
2145 * pCode that is passed in will be the first pCode in the block.
2146 *-----------------------------------------------------------------*/
2149 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2152 pBlock *pB = newpBlock();
2154 pB->pcHead = pB->pcTail = pc;
2161 /*-----------------------------------------------------------------*/
2162 /* newpCodeOpLabel - Create a new label given the key */
2163 /* Note, a negative key means that the label is part of wild card */
2164 /* (and hence a wild card label) used in the pCodePeep */
2165 /* optimizations). */
2166 /*-----------------------------------------------------------------*/
2168 pCodeOp *newpCodeOpLabel(char *name, int key)
2171 static int label_key=-1;
2175 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2176 pcop->type = PO_LABEL;
2181 sprintf(s=buffer,"_%05d_DS_",key);
2183 s = name, key = label_key--;
2185 PCOLAB(pcop)->offset = 0;
2187 pcop->name = Safe_strdup(s);
2189 ((pCodeOpLabel *)pcop)->key = key;
2191 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2195 /*-----------------------------------------------------------------*/
2196 /*-----------------------------------------------------------------*/
2197 pCodeOp *newpCodeOpLit(int lit)
2203 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2204 pcop->type = PO_LITERAL;
2208 sprintf(s,"0x%02x",lit);
2210 pcop->name = Safe_strdup(s);
2213 ((pCodeOpLit *)pcop)->lit = lit;
2218 /*-----------------------------------------------------------------*/
2219 /*-----------------------------------------------------------------*/
2220 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2224 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2225 pcop->type = PO_IMMEDIATE;
2228 pcop->name = Safe_strdup(name);
2231 r = dirregWithName(name);
2235 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2236 PCOI(pcop)->rIdx = r->rIdx;
2238 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2239 PCOI(pcop)->rIdx = -1;
2241 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2246 PCOI(pcop)->index = index;
2247 PCOI(pcop)->offset = offset;
2248 PCOI(pcop)->_const = code_space;
2249 PCOI(pcop)->_function = is_func;
2254 /*-----------------------------------------------------------------*/
2255 /*-----------------------------------------------------------------*/
2256 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2262 if(!pcwb || !subtype) {
2263 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2267 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2268 pcop->type = PO_WILD;
2269 sprintf(s,"%%%d",id);
2270 pcop->name = Safe_strdup(s);
2272 PCOW(pcop)->id = id;
2273 PCOW(pcop)->pcwb = pcwb;
2274 PCOW(pcop)->subtype = subtype;
2275 PCOW(pcop)->matched = NULL;
2279 /*-----------------------------------------------------------------*/
2280 /* Find a symbol with matching name */
2281 /*-----------------------------------------------------------------*/
2282 static symbol *symFindWithName(memmap * map, const char *name)
2286 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2287 if (sym->rname && (strcmp(sym->rname,name)==0))
2293 /*-----------------------------------------------------------------*/
2294 /*-----------------------------------------------------------------*/
2295 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2300 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2301 pcop->type = PO_GPR_BIT;
2303 PCORB(pcop)->bit = ibit;
2304 PCORB(pcop)->inBitSpace = inBitSpace;
2306 if (name) r = regFindWithName(name);
2308 // Register has not been allocated - check for symbol information
2310 sym = symFindWithName(bit, name);
2311 if (!sym) sym = symFindWithName(sfrbit, name);
2312 if (!sym) sym = symFindWithName(sfr, name);
2314 r = allocNewDirReg(sym->etype,name);
2320 PCOR(pcop)->rIdx = r->rIdx;
2322 pcop->name = Safe_strdup(name);
2323 PCOR(pcop)->r = NULL;
2324 PCOR(pcop)->rIdx = 0;
2329 /*-----------------------------------------------------------------*
2330 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2332 * If rIdx >=0 then a specific register from the set of registers
2333 * will be selected. If rIdx <0, then a new register will be searched
2335 *-----------------------------------------------------------------*/
2337 pCodeOp *newpCodeOpReg(int rIdx)
2341 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2346 PCOR(pcop)->rIdx = rIdx;
2347 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2349 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2352 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2356 pcop->type = PCOR(pcop)->r->pc_type;
2361 pCodeOp *newpCodeOpRegFromStr(char *name)
2365 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2366 PCOR(pcop)->r = allocRegByName(name, 1);
2367 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2368 pcop->type = PCOR(pcop)->r->pc_type;
2369 pcop->name = PCOR(pcop)->r->name;
2374 pCodeOp *newpCodeOpStr(char *name)
2378 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2379 pcop->type = PO_STR;
2380 pcop->name = Safe_strdup(name);
2382 PCOS(pcop)->isPublic = 0;
2388 /*-----------------------------------------------------------------*/
2389 /*-----------------------------------------------------------------*/
2391 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2398 pcop = newpCodeOpBit(name, -1,0);
2402 pcop = newpCodeOpLit(-1);
2406 pcop = newpCodeOpLabel(NULL,-1);
2410 pcop = newpCodeOpReg(-1);
2413 case PO_GPR_POINTER:
2414 case PO_GPR_REGISTER:
2416 pcop = newpCodeOpRegFromStr(name);
2418 pcop = newpCodeOpReg(-1);
2422 pcop = newpCodeOpStr(name);
2426 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2429 pcop->name = Safe_strdup(name);
2437 /*-----------------------------------------------------------------*/
2438 /*-----------------------------------------------------------------*/
2439 void pCodeConstString(char *name, char *value)
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);
2454 for (i=strlen(buffer); i--; ) {
2455 unsigned char c = buffer[i];
2456 if (c=='\r' || c=='\n') {
2457 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2459 if (c=='\r') buffer[i+1] = 'r';
2460 else if (c=='\n') buffer[i+1] = 'n';
2464 addpCode2pBlock(pb,newpCodeCharP(buffer));
2465 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2468 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2474 /*-----------------------------------------------------------------*/
2475 /*-----------------------------------------------------------------*/
2476 void pCodeReadCodeTable(void)
2480 fprintf(stderr, " %s\n",__FUNCTION__);
2482 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2486 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2487 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2488 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2489 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2491 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2492 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2493 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2494 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2499 /*-----------------------------------------------------------------*/
2500 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2501 /*-----------------------------------------------------------------*/
2502 void addpCode2pBlock(pBlock *pb, pCode *pc)
2509 /* If this is the first pcode to be added to a block that
2510 * was initialized with a NULL pcode, then go ahead and
2511 * make this pcode the head and tail */
2512 pb->pcHead = pb->pcTail = pc;
2515 pb->pcTail->next = pc;
2517 pc->prev = pb->pcTail;
2524 /*-----------------------------------------------------------------*/
2525 /* addpBlock - place a pBlock into the pFile */
2526 /*-----------------------------------------------------------------*/
2527 void addpBlock(pBlock *pb)
2529 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2532 /* First time called, we'll pass through here. */
2533 //_ALLOC(the_pFile,sizeof(pFile));
2534 the_pFile = Safe_calloc(1,sizeof(pFile));
2535 the_pFile->pbHead = the_pFile->pbTail = pb;
2536 the_pFile->functions = NULL;
2540 the_pFile->pbTail->next = pb;
2541 pb->prev = the_pFile->pbTail;
2543 the_pFile->pbTail = pb;
2546 /*-----------------------------------------------------------------*/
2547 /* removepBlock - remove a pBlock from the pFile */
2548 /*-----------------------------------------------------------------*/
2549 void removepBlock(pBlock *pb)
2557 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2559 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2562 if(pbs == the_pFile->pbHead)
2563 the_pFile->pbHead = pbs->next;
2565 if (pbs == the_pFile->pbTail)
2566 the_pFile->pbTail = pbs->prev;
2569 pbs->next->prev = pbs->prev;
2572 pbs->prev->next = pbs->next;
2579 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2583 /*-----------------------------------------------------------------*/
2584 /* printpCode - write the contents of a pCode to a file */
2585 /*-----------------------------------------------------------------*/
2586 void printpCode(FILE *of, pCode *pc)
2597 fprintf(of,"warning - unable to print pCode\n");
2600 /*-----------------------------------------------------------------*/
2601 /* printpBlock - write the contents of a pBlock to a file */
2602 /*-----------------------------------------------------------------*/
2603 void printpBlock(FILE *of, pBlock *pb)
2613 for(pc = pb->pcHead; pc; pc = pc->next)
2618 /*-----------------------------------------------------------------*/
2620 /* pCode processing */
2624 /*-----------------------------------------------------------------*/
2626 void unlinkpCode(pCode *pc)
2632 fprintf(stderr,"Unlinking: ");
2633 printpCode(stderr, pc);
2636 pc->prev->next = pc->next;
2638 pc->next->prev = pc->prev;
2640 pc->prev = pc->next = NULL;
2644 /*-----------------------------------------------------------------*/
2645 /*-----------------------------------------------------------------*/
2647 static void genericDestruct(pCode *pc)
2653 /* For instructions, tell the register (if there's one used)
2654 * that it's no longer needed */
2655 regs *reg = getRegFromInstruction(pc);
2657 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2660 /* Instead of deleting the memory used by this pCode, mark
2661 * the object as bad so that if there's a pointer to this pCode
2662 * dangling around somewhere then (hopefully) when the type is
2663 * checked we'll catch it.
2668 addpCode2pBlock(pb_dead_pcodes, pc);
2675 /*-----------------------------------------------------------------*/
2676 /* Copies the pCodeInstruction flow pointer from source pCode */
2677 /*-----------------------------------------------------------------*/
2678 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2680 pCodeFlow *pcflow = 0;
2681 for (p=pcs; p; p=p->prev) {
2683 pcflow = PCI(p)->pcflow;
2687 pcflow = (pCodeFlow*)p;
2691 PCI(pcd)->pcflow = pcflow;
2694 /*-----------------------------------------------------------------*/
2695 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2696 /* into the pCode chain containing pc1 */
2697 /*-----------------------------------------------------------------*/
2698 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2704 pc2->next = pc1->next;
2706 pc1->next->prev = pc2;
2712 /* If this is an instrution type propogate the flow */
2714 CopyFlow(PCI(pc2),pc1);
2717 /*------------------------------------------------------------------*/
2718 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2719 /* into the pCode chain containing pc1 */
2720 /*------------------------------------------------------------------*/
2721 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2727 pc2->prev = pc1->prev;
2729 pc1->prev->next = pc2;
2735 /* If this is an instrution type propogate the flow */
2737 CopyFlow(PCI(pc2),pc1);
2740 /*-----------------------------------------------------------------*/
2741 /* pCodeOpCopy - copy a pcode operator */
2742 /*-----------------------------------------------------------------*/
2743 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2745 pCodeOp *pcopnew=NULL;
2750 switch(pcop->type) {
2753 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2754 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2755 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2756 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2761 /* Here we expand the wild card into the appropriate type: */
2762 /* By recursively calling pCodeOpCopy */
2763 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2764 if(PCOW(pcop)->matched)
2765 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2768 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2769 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2770 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2777 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2778 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2779 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2783 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2784 PCOI(pcopnew)->index = PCOI(pcop)->index;
2785 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2786 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2787 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2791 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2792 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2793 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2798 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2799 PCOR(pcopnew)->r = PCOR(pcop)->r;
2800 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2801 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2805 case PO_GPR_POINTER:
2806 case PO_GPR_REGISTER:
2810 //DFPRINTF((stderr,"pCodeOpCopy GPR register\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;
2815 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2819 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2820 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2821 PCOR(pcopnew)->r = PCOR(pcop)->r;
2822 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2823 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2826 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2827 case PO_SFR_REGISTER:
2835 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2836 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2840 pcopnew->type = pcop->type;
2842 pcopnew->name = Safe_strdup(pcop->name);
2844 pcopnew->name = NULL;
2849 /*-----------------------------------------------------------------*/
2850 /* popCopyReg - copy a pcode operator */
2851 /*-----------------------------------------------------------------*/
2852 pCodeOp *popCopyReg(pCodeOpReg *pc)
2856 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2857 pcor->pcop.type = pc->pcop.type;
2859 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2860 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2862 pcor->pcop.name = NULL;
2864 if (pcor->pcop.type == PO_IMMEDIATE){
2865 PCOL(pcor)->lit = PCOL(pc)->lit;
2868 pcor->rIdx = pc->rIdx;
2872 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2877 /*-----------------------------------------------------------------*/
2878 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2879 /*-----------------------------------------------------------------*/
2880 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2882 pCodeInstruction *new_pci;
2885 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2887 new_pci = PCI(newpCode(pci->op,pci->pcop));
2889 new_pci->pc.pb = pci->pc.pb;
2890 new_pci->from = pci->from;
2891 new_pci->to = pci->to;
2892 new_pci->label = pci->label;
2893 new_pci->pcflow = pci->pcflow;
2895 return PCODE(new_pci);
2898 /*-----------------------------------------------------------------*/
2899 /*-----------------------------------------------------------------*/
2900 void pCodeDeleteChain(pCode *f,pCode *t)
2905 DFPRINTF((stderr,"delete pCode:\n"));
2907 //f->print(stderr,f);
2908 //f->delete(f); this dumps core...
2913 /*-----------------------------------------------------------------*/
2914 /*-----------------------------------------------------------------*/
2915 void pBlockRegs(FILE *of, pBlock *pb)
2920 r = setFirstItem(pb->tregisters);
2922 r = setNextItem(pb->tregisters);
2927 /*-----------------------------------------------------------------*/
2928 /*-----------------------------------------------------------------*/
2929 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2934 int use_buffer = 1; // copy the string to the passed buffer pointer
2939 use_buffer = 0; // Don't bother copying the string to the buffer.
2943 switch(pcop->type) {
2947 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2950 //return PCOR(pcop)->r->name;
2954 if (PCOR(pcop)->r->type == REG_STK)
2955 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2957 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2960 SAFE_snprintf(&buffer,&size,"%s",r->name);
2969 if(PCOI(pcop)->_const) {
2971 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2972 switch(PCOI(pcop)->offset) {
2974 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2977 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2980 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2983 8 * PCOI(pcop)->offset );
2986 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2988 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) {
2989 SAFE_snprintf(&s,&size,"(%s + %d)",
2993 switch(PCOI(pcop)->offset) {
2995 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
2998 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3001 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3011 //size = sizeof(buffer);
3012 if( PCOR(pcop)->instance) {
3013 SAFE_snprintf(&s,&size,"(%s + %d)",
3015 PCOR(pcop)->instance );
3016 //fprintf(stderr,"PO_DIR %s\n",buffer);
3018 SAFE_snprintf(&s,&size,"%s",pcop->name);
3024 if(PCOLAB(pcop)->offset == 1)
3025 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3027 SAFE_snprintf(&s,&size,"%s",pcop->name);
3034 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3037 return PCOR(pcop)->r->name;
3040 /* fall through to the default case */
3044 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3052 printf("PIC port internal warning: (%s:%d) %s not found\n",
3057 return "NO operand";
3061 /*-----------------------------------------------------------------*/
3062 /*-----------------------------------------------------------------*/
3063 static char *get_op_from_instruction( pCodeInstruction *pcc)
3067 return get_op(pcc->pcop,NULL,0);
3069 return ("ERROR Null: get_op_from_instruction");
3073 /*-----------------------------------------------------------------*/
3074 /*-----------------------------------------------------------------*/
3075 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3077 fprintf(of,"pcodeopprint- not implemented\n");
3080 /*-----------------------------------------------------------------*/
3081 /* pCode2str - convert a pCode instruction to string */
3082 /*-----------------------------------------------------------------*/
3083 char *pCode2str(char *str, size_t size, pCode *pc)
3091 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3093 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3095 if(PCI(pc)->isBitInst) {
3096 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3097 char *name = PCI(pc)->pcop->name;
3099 name = PCOR(PCI(pc)->pcop)->r->name;
3100 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3101 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3103 SAFE_snprintf(&s,&size,"%s,%d", name,
3104 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3105 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3106 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3108 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3109 //PCI(pc)->pcop->t.bit );
3111 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3112 if( PCI(pc)->num_ops == 2)
3113 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3115 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3117 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3118 if( PCI(pc)->num_ops == 2)
3119 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3126 /* assuming that comment ends with a \n */
3127 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3131 /* assuming that inline code ends with a \n */
3132 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3136 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3139 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3142 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3145 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3148 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3151 if(PCAD(pc)->directive) {
3152 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3153 } else if(PCAD(pc)->arg) {
3154 /* special case to handle inline labels without a tab */
3155 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3160 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3166 /*-----------------------------------------------------------------*/
3167 /* genericPrint - the contents of a pCode to a file */
3168 /*-----------------------------------------------------------------*/
3169 static void genericPrint(FILE *of, pCode *pc)
3176 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3180 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3184 // If the opcode has a label, print that first
3187 pCodeInstruction *pci = PCI(pc);
3188 pBranch *pbl = pci->label;
3189 while(pbl && pbl->pc) {
3190 if(pbl->pc->type == PC_LABEL)
3191 pCodePrintLabel(of, pbl->pc);
3196 genericPrint(of,PCODE(pci->cline));
3199 pCode2str(str, 256, pc);
3201 fprintf(of,"%s",str);
3205 pCodeOpReg *pcor = PCOR(pci->pcop);
3206 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3208 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3209 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3210 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3215 pBranch *dpb = pc->to; // debug
3217 switch ( dpb->pc->type) {
3219 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3222 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3225 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3228 fprintf(of, "\t;flow");
3242 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3243 if(PCW(pc)->pci.label)
3244 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3246 if(PCW(pc)->operand) {
3247 fprintf(of,";\toperand ");
3248 pCodeOpPrint(of,PCW(pc)->operand );
3254 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3255 if(PCFL(pc)->ancestor)
3256 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3262 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3267 pBranch *pbl = PCAD(pc)->pci.label;
3268 while(pbl && pbl->pc) {
3269 if(pbl->pc->type == PC_LABEL)
3270 pCodePrintLabel(of, pbl->pc);
3274 if(PCAD(pc)->directive) {
3275 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3278 /* special case to handle inline labels without tab */
3279 fprintf(of, "%s\n", PCAD(pc)->arg);
3285 fprintf(of,"unknown pCode type %d\n",pc->type);
3289 /*-----------------------------------------------------------------*/
3290 /* pCodePrintFunction - prints function begin/end */
3291 /*-----------------------------------------------------------------*/
3293 static void pCodePrintFunction(FILE *of, pCode *pc)
3299 if( ((pCodeFunction *)pc)->modname)
3300 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3302 if(PCF(pc)->fname) {
3303 pBranch *exits = PCF(pc)->to;
3305 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3308 exits = exits->next;
3311 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3314 if((PCF(pc)->from &&
3315 PCF(pc)->from->pc->type == PC_FUNCTION &&
3316 PCF(PCF(pc)->from->pc)->fname) )
3317 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3319 fprintf(of,"; exit point [can't find entry point]\n");
3322 /*-----------------------------------------------------------------*/
3323 /* pCodePrintLabel - prints label */
3324 /*-----------------------------------------------------------------*/
3326 static void pCodePrintLabel(FILE *of, pCode *pc)
3333 fprintf(of,"%s\n",PCL(pc)->label);
3334 else if (PCL(pc)->key >=0)
3335 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3337 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3341 /*-----------------------------------------------------------------*/
3342 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3343 /* remove it if it is found. */
3344 /*-----------------------------------------------------------------*/
3345 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3351 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3352 b = PCI(pcl)->label;
3354 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3358 //fprintf (stderr, "%s \n",__FUNCTION__);
3359 //pcl->print(stderr,pcl);
3360 //pc->print(stderr,pc);
3363 //fprintf (stderr, "found label\n");
3367 bprev->next = b->next; /* Not first pCode in chain */
3371 PCI(pcl)->label = b->next; /* First pCode in chain */
3374 return; /* A label can't occur more than once */
3381 /*-----------------------------------------------------------------*/
3382 /*-----------------------------------------------------------------*/
3383 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3402 /*-----------------------------------------------------------------*/
3403 /* pBranchLink - given two pcodes, this function will link them */
3404 /* together through their pBranches */
3405 /*-----------------------------------------------------------------*/
3406 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3410 // Declare a new branch object for the 'from' pCode.
3412 //_ALLOC(b,sizeof(pBranch));
3413 b = Safe_calloc(1,sizeof(pBranch));
3414 b->pc = PCODE(t); // The link to the 'to' pCode.
3417 f->to = pBranchAppend(f->to,b);
3419 // Now do the same for the 'to' pCode.
3421 //_ALLOC(b,sizeof(pBranch));
3422 b = Safe_calloc(1,sizeof(pBranch));
3426 t->from = pBranchAppend(t->from,b);
3431 /*-----------------------------------------------------------------*/
3432 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3434 /*-----------------------------------------------------------------*/
3435 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3448 /*-----------------------------------------------------------------*/
3449 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3450 /*-----------------------------------------------------------------*/
3451 static void pCodeUnlink(pCode *pc)
3456 if(!pc->prev || !pc->next) {
3457 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3461 /* first remove the pCode from the chain */
3462 pc->prev->next = pc->next;
3463 pc->next->prev = pc->prev;
3465 /* Now for the hard part... */
3467 /* Remove the branches */
3471 pc1 = pb1->pc; /* Get the pCode that branches to the
3472 * one we're unlinking */
3474 /* search for the link back to this pCode (the one we're
3476 if(pb2 = pBranchFind(pc1->to,pc)) {
3477 pb2->pc = pc->to->pc; // make the replacement
3479 /* if the pCode we're unlinking contains multiple 'to'
3480 * branches (e.g. this a skip instruction) then we need
3481 * to copy these extra branches to the chain. */
3483 pBranchAppend(pb2, pc->to->next);
3492 /*-----------------------------------------------------------------*/
3493 /*-----------------------------------------------------------------*/
3495 static void genericAnalyze(pCode *pc)
3505 // Go through the pCodes that are in pCode chain and link
3506 // them together through the pBranches. Note, the pCodes
3507 // are linked together as a contiguous stream like the
3508 // assembly source code lines. The linking here mimics this
3509 // except that comments are not linked in.
3511 pCode *npc = pc->next;
3513 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3514 pBranchLink(pc,npc);
3519 /* reached the end of the pcode chain without finding
3520 * an instruction we could link to. */
3524 fprintf(stderr,"analyze PC_FLOW\n");
3528 fprintf(stderr,";A bad pCode is being used\n");
3534 /*-----------------------------------------------------------------*/
3535 /*-----------------------------------------------------------------*/
3536 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3540 if(pc->type == PC_LABEL) {
3541 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3544 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3545 pbr = PCI(pc)->label;
3547 if(pbr->pc->type == PC_LABEL) {
3548 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3558 /*-----------------------------------------------------------------*/
3559 /*-----------------------------------------------------------------*/
3560 int checkLabel(pCode *pc)
3564 if(pc && isPCI(pc)) {
3565 pbr = PCI(pc)->label;
3567 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3577 /*-----------------------------------------------------------------*/
3578 /* findLabelinpBlock - Search the pCode for a particular label */
3579 /*-----------------------------------------------------------------*/
3580 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3587 for(pc = pb->pcHead; pc; pc = pc->next)
3588 if(compareLabel(pc,pcop_label))
3594 /*-----------------------------------------------------------------*/
3595 /* findLabel - Search the pCode for a particular label */
3596 /*-----------------------------------------------------------------*/
3597 pCode * findLabel(pCodeOpLabel *pcop_label)
3605 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3606 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3610 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3614 /*-----------------------------------------------------------------*/
3615 /* findNextpCode - given a pCode, find the next of type 'pct' */
3616 /* in the linked list */
3617 /*-----------------------------------------------------------------*/
3618 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3631 /*-----------------------------------------------------------------*/
3632 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3633 /* in the linked list */
3634 /*-----------------------------------------------------------------*/
3635 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3639 if(pc->type == pct) {
3641 static unsigned int stop;
3643 stop++; // Place break point here
3654 /*-----------------------------------------------------------------*/
3655 /* findNextInstruction - given a pCode, find the next instruction */
3656 /* in the linked list */
3657 /*-----------------------------------------------------------------*/
3658 pCode * findNextInstruction(pCode *pci)
3663 if((pc->type == PC_OPCODE)
3664 || (pc->type == PC_WILD)
3665 || (pc->type == PC_ASMDIR))
3669 fprintf(stderr,"findNextInstruction: ");
3670 printpCode(stderr, pc);
3675 //fprintf(stderr,"Couldn't find instruction\n");
3679 /*-----------------------------------------------------------------*/
3680 /* findNextInstruction - given a pCode, find the next instruction */
3681 /* in the linked list */
3682 /*-----------------------------------------------------------------*/
3683 pCode * findPrevInstruction(pCode *pci)
3689 if((pc->type == PC_OPCODE)
3690 || (pc->type == PC_WILD)
3691 || (pc->type == PC_ASMDIR))
3696 fprintf(stderr,"pic16_findPrevInstruction: ");
3697 printpCode(stderr, pc);
3702 //fprintf(stderr,"Couldn't find instruction\n");
3706 /*-----------------------------------------------------------------*/
3707 /* findFunctionEnd - given a pCode find the end of the function */
3708 /* that contains it */
3709 /*-----------------------------------------------------------------*/
3710 pCode * findFunctionEnd(pCode *pc)
3713 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3719 fprintf(stderr,"Couldn't find function end\n");
3724 /*-----------------------------------------------------------------*/
3725 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3726 /* instruction with which it is associated. */
3727 /*-----------------------------------------------------------------*/
3728 static void AnalyzeLabel(pCode *pc)
3737 static void AnalyzeGOTO(pCode *pc)
3740 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3744 static void AnalyzeSKIP(pCode *pc)
3747 pBranchLink(pc,findNextInstruction(pc->next));
3748 pBranchLink(pc,findNextInstruction(pc->next->next));
3752 static void AnalyzeRETURN(pCode *pc)
3755 // branch_link(pc,findFunctionEnd(pc->next));
3761 /*-----------------------------------------------------------------*/
3762 /*-----------------------------------------------------------------*/
3763 regs * getRegFromInstruction(pCode *pc)
3769 PCI(pc)->num_ops == 0 )
3772 switch(PCI(pc)->pcop->type) {
3775 return PCOR(PCI(pc)->pcop)->r;
3779 return PCOR(PCI(pc)->pcop)->r;
3782 r = PCOI(PCI(pc)->pcop)->r;
3785 return dirregWithName(PCI(pc)->pcop->name);
3788 r = PCOR(PCI(pc)->pcop)->r;
3791 return dirregWithName(PCI(pc)->pcop->name);
3793 case PO_GPR_REGISTER:
3795 r = PCOR(PCI(pc)->pcop)->r;
3798 return dirregWithName(PCI(pc)->pcop->name);
3810 /*-----------------------------------------------------------------*/
3811 /*-----------------------------------------------------------------*/
3813 void AnalyzepBlock(pBlock *pb)
3820 /* Find all of the registers used in this pBlock
3821 * by looking at each instruction and examining it's
3824 for(pc = pb->pcHead; pc; pc = pc->next) {
3826 /* Is this an instruction with operands? */
3827 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3829 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3830 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3832 /* Loop through all of the registers declared so far in
3833 this block and see if we find this one there */
3835 regs *r = setFirstItem(pb->tregisters);
3838 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3839 PCOR(PCI(pc)->pcop)->r = r;
3842 r = setNextItem(pb->tregisters);
3846 /* register wasn't found */
3847 //r = Safe_calloc(1, sizeof(regs));
3848 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3849 //addSet(&pb->tregisters, r);
3850 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3851 //PCOR(PCI(pc)->pcop)->r = r;
3852 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3854 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3857 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3858 if(PCOR(PCI(pc)->pcop)->r) {
3859 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3860 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3862 if(PCI(pc)->pcop->name)
3863 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3865 fprintf(stderr,"ERROR: NULL register\n");
3874 /*-----------------------------------------------------------------*/
3876 /*-----------------------------------------------------------------*/
3877 void InsertpFlow(pCode *pc, pCode **pflow)
3880 PCFL(*pflow)->end = pc;
3882 if(!pc || !pc->next)
3885 *pflow = newpCodeFlow();
3886 pCodeInsertAfter(pc, *pflow);
3889 /*-----------------------------------------------------------------*/
3890 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3891 /* the flow blocks. */
3893 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3894 * point the instruction flow changes.
3896 /*-----------------------------------------------------------------*/
3897 void BuildFlow(pBlock *pb)
3900 pCode *last_pci=NULL;
3907 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3908 /* Insert a pCodeFlow object at the beginning of a pBlock */
3910 InsertpFlow(pb->pcHead, &pflow);
3912 //pflow = newpCodeFlow(); /* Create a new Flow object */
3913 //pflow->next = pb->pcHead; /* Make the current head the next object */
3914 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3915 //pb->pcHead = pflow; /* Make the Flow object the head */
3918 for( pc = findNextInstruction(pb->pcHead);
3920 pc=findNextInstruction(pc)) {
3923 PCI(pc)->pcflow = PCFL(pflow);
3925 //fprintf(stderr," build: ");
3926 //pflow->print(stderr,pflow);
3928 if( PCI(pc)->isSkip) {
3930 /* The two instructions immediately following this one
3931 * mark the beginning of a new flow segment */
3933 while(pc && PCI(pc)->isSkip) {
3935 PCI(pc)->pcflow = PCFL(pflow);
3939 InsertpFlow(pc, &pflow);
3940 pc=findNextInstruction(pc->next);
3948 PCI(pc)->pcflow = PCFL(pflow);
3950 InsertpFlow(pc, &pflow);
3952 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3954 InsertpFlow(pc, &pflow);
3957 } else if (checkLabel(pc)) {
3959 /* This instruction marks the beginning of a
3960 * new flow segment */
3965 /* If the previous pCode is not a flow object, then
3966 * insert a new flow object. (This check prevents
3967 * two consecutive flow objects from being insert in
3968 * the case where a skip instruction preceeds an
3969 * instruction containing a label.) */
3971 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3972 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3974 PCI(pc)->pcflow = PCFL(pflow);
3981 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3983 PCFL(pflow)->end = pb->pcTail;
3986 /*-------------------------------------------------------------------*/
3987 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3988 /* the flow blocks. */
3990 * unBuildFlow removes pCodeFlow objects from a pCode chain
3992 /*-----------------------------------------------------------------*/
3993 void unBuildFlow(pBlock *pb)
4008 if(PCI(pc)->pcflow) {
4009 //free(PCI(pc)->pcflow);
4010 PCI(pc)->pcflow = NULL;
4013 } else if(isPCFL(pc) )
4022 /*-----------------------------------------------------------------*/
4023 /*-----------------------------------------------------------------*/
4024 void dumpCond(int cond)
4027 static char *pcc_str[] = {
4041 int ncond = sizeof(pcc_str) / sizeof(char *);
4044 fprintf(stderr, "0x%04X\n",cond);
4046 for(i=0,j=1; i<ncond; i++, j<<=1)
4048 fprintf(stderr, " %s\n",pcc_str[i]);
4052 /*-----------------------------------------------------------------*/
4053 /*-----------------------------------------------------------------*/
4054 void FlowStats(pCodeFlow *pcflow)
4062 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4064 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4067 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4072 fprintf(stderr, " FlowStats inCond: ");
4073 dumpCond(pcflow->inCond);
4074 fprintf(stderr, " FlowStats outCond: ");
4075 dumpCond(pcflow->outCond);
4079 /*-----------------------------------------------------------------*
4080 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4081 * if it affects the banking bits.
4083 * return: -1 == Banking bits are unaffected by this pCode.
4085 * return: > 0 == Banking bits are affected.
4087 * If the banking bits are affected, then the returned value describes
4088 * which bits are affected and how they're affected. The lower half
4089 * of the integer maps to the bits that are affected, the upper half
4090 * to whether they're set or cleared.
4092 *-----------------------------------------------------------------*/
4094 #define SET_BANK_BIT (1 << 16)
4095 #define CLR_BANK_BIT 0
4097 static int isBankInstruction(pCode *pc)
4105 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4107 // Check to see if the register banks are changing
4108 if(PCI(pc)->isModReg) {
4110 pCodeOp *pcop = PCI(pc)->pcop;
4111 switch(PCI(pc)->op) {
4114 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4115 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4116 return SET_BANK_BIT | PIC_RP0_BIT;
4119 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4120 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4121 return CLR_BANK_BIT | PIC_RP0_BIT;
4126 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4127 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4128 return CLR_BANK_BIT | PIC_RP1_BIT;
4130 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4131 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4132 return CLR_BANK_BIT | PIC_RP1_BIT;
4136 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4137 //genericPrint(stderr, pc);
4148 /*-----------------------------------------------------------------*/
4149 /*-----------------------------------------------------------------*/
4151 static void FillFlow(pCodeFlow *pcflow)
4159 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4161 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4164 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4171 isBankInstruction(pc);
4173 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4176 fprintf(stderr, " FillFlow - Bad end of flow\n");
4178 fprintf(stderr, " FillFlow - Ending flow with\n ");
4179 pc->print(stderr,pc);
4182 fprintf(stderr, " FillFlow inCond: ");
4183 dumpCond(pcflow->inCond);
4184 fprintf(stderr, " FillFlow outCond: ");
4185 dumpCond(pcflow->outCond);
4190 /*-----------------------------------------------------------------*/
4191 /*-----------------------------------------------------------------*/
4192 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4194 pCodeFlowLink *fromLink, *toLink;
4196 if(!from || !to || !to->pcflow || !from->pcflow)
4199 fromLink = newpCodeFlowLink(from->pcflow);
4200 toLink = newpCodeFlowLink(to->pcflow);
4202 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4203 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4207 /*-----------------------------------------------------------------*
4208 * void LinkFlow(pBlock *pb)
4210 * In BuildFlow, the PIC code has been partitioned into contiguous
4211 * non-branching segments. In LinkFlow, we determine the execution
4212 * order of these segments. For example, if one of the segments ends
4213 * with a skip, then we know that there are two possible flow segments
4214 * to which control may be passed.
4215 *-----------------------------------------------------------------*/
4216 void LinkFlow(pBlock *pb)
4222 //fprintf(stderr,"linkflow \n");
4224 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4226 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4229 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4231 //fprintf(stderr," link: ");
4232 //pcflow->print(stderr,pcflow);
4234 //FillFlow(PCFL(pcflow));
4236 pc = PCFL(pcflow)->end;
4238 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4239 if(isPCI_SKIP(pc)) {
4240 //fprintf(stderr, "ends with skip\n");
4241 //pc->print(stderr,pc);
4242 pct=findNextInstruction(pc->next);
4243 LinkFlow_pCode(PCI(pc),PCI(pct));
4244 pct=findNextInstruction(pct->next);
4245 LinkFlow_pCode(PCI(pc),PCI(pct));
4249 if(isPCI_BRANCH(pc)) {
4250 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4252 //fprintf(stderr, "ends with branch\n ");
4253 //pc->print(stderr,pc);
4255 if(!(pcol && isPCOLAB(pcol))) {
4256 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4257 pc->print(stderr,pc);
4258 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4263 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4264 LinkFlow_pCode(PCI(pc),PCI(pct));
4266 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4267 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4268 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4274 //fprintf(stderr, "ends with non-branching instruction:\n");
4275 //pc->print(stderr,pc);
4277 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4283 //fprintf(stderr, "ends with unknown\n");
4284 //pc->print(stderr,pc);
4288 //fprintf(stderr, "ends with nothing: ERROR\n");
4292 /*-----------------------------------------------------------------*/
4293 /*-----------------------------------------------------------------*/
4295 /*-----------------------------------------------------------------*/
4296 /*-----------------------------------------------------------------*/
4297 int isPCinFlow(pCode *pc, pCode *pcflow)
4303 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4306 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4312 /*-----------------------------------------------------------------*/
4313 /*-----------------------------------------------------------------*/
4315 static void BanksUsedFlow2(pCode *pcflow)
4324 if(!isPCFL(pcflow)) {
4325 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4329 pc = findNextInstruction(pcflow->next);
4331 PCFL(pcflow)->lastBank = -1;
4333 while(isPCinFlow(pc,pcflow)) {
4335 int bank_selected = isBankInstruction(pc);
4337 //if(PCI(pc)->pcflow)
4338 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4340 if(bank_selected > 0) {
4341 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4343 // This instruction is modifying banking bits before accessing registers
4345 PCFL(pcflow)->firstBank = -1;
4347 if(PCFL(pcflow)->lastBank == -1)
4348 PCFL(pcflow)->lastBank = 0;
4350 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4351 if(bank_selected & SET_BANK_BIT)
4352 PCFL(pcflow)->lastBank |= bank;
4356 reg = getRegFromInstruction(pc);
4358 if(reg && !isREGinBank(reg, bank)) {
4359 int allbanks = REGallBanks(reg);
4361 PCFL(pcflow)->firstBank = allbanks;
4363 PCFL(pcflow)->lastBank = allbanks;
4370 pc = findNextInstruction(pc->next);
4373 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4374 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4377 /*-----------------------------------------------------------------*/
4378 /*-----------------------------------------------------------------*/
4380 static void BanksUsedFlow(pBlock *pb)
4385 //pb->pcHead->print(stderr, pb->pcHead);
4387 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4388 //pcflow->print(stderr,pcflow);
4390 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4392 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4394 BanksUsedFlow2(pcflow);
4400 /*-----------------------------------------------------------------*/
4401 /* Inserts a new pCodeInstruction before an existing one */
4402 /*-----------------------------------------------------------------*/
4403 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4406 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4408 /* Move the label, if there is one */
4411 new_pci->label = pci->label;
4415 /* Move the C code comment, if there is one */
4418 new_pci->cline = pci->cline;
4422 /* The new instruction has the same pcflow block */
4423 new_pci->pcflow = pci->pcflow;
4427 /*-----------------------------------------------------------------*/
4428 /*-----------------------------------------------------------------*/
4429 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4433 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4435 insertPCodeInstruction(pci, PCI(new_pc));
4438 /*-----------------------------------------------------------------*/
4439 /*-----------------------------------------------------------------*/
4440 static void insertBankSel(pCodeInstruction *pci, const char *name)
4444 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4445 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4446 if (pcop->name == 0)
4447 pcop->name = strdup(name);
4448 new_pc = newpCode(POC_BANKSEL, pcop);
4450 insertPCodeInstruction(pci, PCI(new_pc));
4453 /*-----------------------------------------------------------------*/
4454 /* If the register is a fixed known addess then we can assign the */
4455 /* bank selection bits. Otherwise the linker is going to assign */
4456 /* the register location and thus has to set bank selection bits */
4457 /* through the banksel directive. */
4458 /* One critical assumption here is that within this C module all */
4459 /* the locally allocated registers are in the same udata sector. */
4460 /* Therefore banksel is only called for external registers or the */
4461 /* first time a local register is encountered. */
4462 /*-----------------------------------------------------------------*/
4463 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4464 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4467 int a = reg->alias>>7;
4469 return cur_bank; // This register is available in all banks
4470 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4471 return cur_bank; // This register is available in banks 0 & 1
4473 if (reg->address&0x80) {
4474 if ((cur_bank==1)||(cur_bank==3)) {
4475 return cur_bank; // This register is available in banks 1 & 3
4478 if ((cur_bank==0)||(cur_bank==1)) {
4479 return cur_bank; // This register is available in banks 0 & 2
4484 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4486 LastRegIdx = reg->rIdx;
4489 bank = REG_BANK(reg);
4490 } else if (reg->isExtern) {
4491 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4493 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4495 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.
4496 return 'L'; // Local registers are presumed to be in same linker assigned bank
4497 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4498 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4499 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4500 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4501 } 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
4502 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4503 if (getMaxRam()&0x100)
4504 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4505 } else { // Current bank and new register banks known - can set bank bits
4506 switch((cur_bank^bank) & 3) {
4510 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4513 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4516 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4517 if (getMaxRam()&0x100)
4518 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4526 /*-----------------------------------------------------------------*/
4527 /* Check for bank selection pcodes instructions and modify */
4528 /* cur_bank to match. */
4529 /*-----------------------------------------------------------------*/
4530 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4532 if (isSTATUS_REG(reg)) {
4534 if (PCI(pc)->op == POC_BCF) {
4535 int old_bank = *cur_bank;
4536 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4537 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4538 if (*cur_bank & ~(0x3))
4541 *cur_bank = *cur_bank&0x2;
4542 LastRegIdx = reg->rIdx;
4543 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4544 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4545 if (*cur_bank & ~(0x3))
4548 *cur_bank = *cur_bank&0x1;
4549 LastRegIdx = reg->rIdx;
4551 return old_bank != *cur_bank;
4554 if (PCI(pc)->op == POC_BSF) {
4555 int old_bank = *cur_bank;
4556 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4557 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4558 if (*cur_bank & ~(0x3))
4561 *cur_bank = (*cur_bank&0x2) | 0x1;
4562 LastRegIdx = reg->rIdx;
4563 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4564 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4565 if (*cur_bank & ~(0x3))
4568 *cur_bank = (*cur_bank&0x1) | 0x2;
4569 LastRegIdx = reg->rIdx;
4571 return old_bank != *cur_bank;
4574 } else if (PCI(pc)->op == POC_BANKSEL) {
4575 int old_bank = *cur_bank;
4576 regs *r = PCOR(PCI(pc)->pcop)->r;
4577 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4578 LastRegIdx = reg->rIdx;
4579 return old_bank != *cur_bank;
4585 /*-----------------------------------------------------------------*/
4586 /* Set bank selection if necessary */
4587 /*-----------------------------------------------------------------*/
4588 static int DoBankSelect(pCode *pc, int cur_bank) {
4596 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4597 if (pcf && isPCF(pcf)) {
4599 int rbank = 'U'; // Undetermined
4600 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4601 // Check all the returns to work out what bank is selected
4602 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4604 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4606 rbank = PCFL(pcfr)->lastBank;
4608 if (rbank != PCFL(pcfr)->lastBank)
4609 return -1; // Unknown bank - multiple returns with different banks
4614 return -1; // Unknown bank
4616 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4617 /* Extern functions may use registers in different bank - must call banksel */
4618 return -1; /* Unknown bank */
4622 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4623 return -1; /* New bank unknown - linkers choice. */
4626 reg = getRegFromInstruction(pc);
4628 if (IsBankChange(pc,reg,&cur_bank))
4630 if (!isPCI_LIT(pc)) {
4632 /* Examine the instruction before this one to make sure it is
4633 * not a skip type instruction */
4634 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4636 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4637 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4639 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4641 if (!PCI(pc)->pcflow)
4642 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4644 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4650 /*-----------------------------------------------------------------*/
4651 /*-----------------------------------------------------------------*/
4653 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4661 pc = findNextInstruction(pcfl->pc.next);
4663 while(isPCinFlow(pc,PCODE(pcfl))) {
4665 cur_bank = DoBankSelect(pc,cur_bank);
4667 pc = findNextInstruction(pc->next);
4671 if(pcprev && cur_bank) {
4672 // Set bank state to unknown at the end of each flow block
4678 /*-----------------------------------------------------------------*/
4679 /*int compareBankFlow - compare the banking requirements between */
4681 /*-----------------------------------------------------------------*/
4683 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4686 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4689 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4692 if(pcflow->firstBank == -1)
4696 if(pcflowLink->pcflow->firstBank == -1) {
4697 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4698 pcflowLink->pcflow->to :
4699 pcflowLink->pcflow->from);
4700 return compareBankFlow(pcflow, pctl, toORfrom);
4704 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4707 pcflowLink->bank_conflict++;
4708 pcflowLink->pcflow->FromConflicts++;
4709 pcflow->ToConflicts++;
4712 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4715 pcflowLink->bank_conflict++;
4716 pcflowLink->pcflow->ToConflicts++;
4717 pcflow->FromConflicts++;
4721 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4722 pcflowLink->pcflow->pc.seq,
4723 pcflowLink->pcflow->FromConflicts,
4724 pcflowLink->pcflow->ToConflicts);
4730 /*-----------------------------------------------------------------*/
4731 /*-----------------------------------------------------------------*/
4733 void FixBankFlow(pBlock *pb)
4737 pCodeFlowLink *pcfl;
4739 pCode *pcflow_max_To=NULL;
4740 pCode *pcflow_max_From=NULL;
4741 int max_ToConflicts=0;
4742 int max_FromConflicts=0;
4744 /fprintf(stderr,"Fix Bank flow \n");
4745 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4749 First loop through all of the flow objects in this pcode block
4750 and fix the ones that have banking conflicts between the
4754 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4756 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4758 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4760 if(!isPCFL(pcflow)) {
4761 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4765 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4766 PCFL(pcflow)->firstBank >= 0 &&
4767 PCFL(pcflow)->lastBank >= 0 ) {
4769 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4770 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4772 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4773 BanksUsedFlow2(pcflow);
4778 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4780 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4782 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4787 if(!isPCFL(pcflow)) {
4788 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4792 PCFL(pcflow)->FromConflicts = 0;
4793 PCFL(pcflow)->ToConflicts = 0;
4798 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4799 pcfl = setFirstItem(PCFL(pcflow)->from);
4802 pc = PCODE(pcfl->pcflow);
4805 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4806 pc->print(stderr,pc);
4809 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4812 pcfl=setNextItem(PCFL(pcflow)->from);
4815 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4816 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4818 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4819 BanksUsedFlow2(pcflow);
4821 continue; / * Don't need to check the flow from here - it's already been fixed * /
4828 pcfl = setFirstItem(PCFL(pcflow)->to);
4831 pc = PCODE(pcfl->pcflow);
4833 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4834 pc->print(stderr,pc);
4837 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4840 pcfl=setNextItem(PCFL(pcflow)->to);
4843 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4844 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4846 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4847 BanksUsedFlow2(pcflow);
4852 Loop through the flow objects again and find the ones with the
4856 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4858 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4860 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4861 pcflow_max_To = pcflow;
4863 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4864 pcflow_max_From = pcflow;
4868 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4869 PCFL(pcflow_max_To)->pc.seq,
4870 PCFL(pcflow_max_To)->ToConflicts);
4873 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4874 PCFL(pcflow_max_From)->pc.seq,
4875 PCFL(pcflow_max_From)->FromConflicts);
4880 /*-----------------------------------------------------------------*/
4881 /*-----------------------------------------------------------------*/
4882 void DumpFlow(pBlock *pb)
4886 pCodeFlowLink *pcfl;
4889 fprintf(stderr,"Dump flow \n");
4890 pb->pcHead->print(stderr, pb->pcHead);
4892 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4893 pcflow->print(stderr,pcflow);
4895 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4897 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4899 if(!isPCFL(pcflow)) {
4900 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4903 fprintf(stderr,"dumping: ");
4904 pcflow->print(stderr,pcflow);
4905 FlowStats(PCFL(pcflow));
4907 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4909 pc = PCODE(pcfl->pcflow);
4911 fprintf(stderr, " from seq %d:\n",pc->seq);
4913 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4914 pc->print(stderr,pc);
4919 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4921 pc = PCODE(pcfl->pcflow);
4923 fprintf(stderr, " to seq %d:\n",pc->seq);
4925 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4926 pc->print(stderr,pc);
4935 /*-----------------------------------------------------------------*/
4936 /*-----------------------------------------------------------------*/
4937 int OptimizepBlock(pBlock *pb)
4942 if(!pb || !peepOptimizing)
4945 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4947 for(pc = pb->pcHead; pc; pc = pc->next)
4948 matches += pCodePeepMatchRule(pc);
4951 pc = findNextInstruction(pb->pcHead);
4959 if(pCodePeepMatchRule(pc)) {
4964 pc = findNextInstruction(pcprev->next);
4966 pc = findNextInstruction(pb->pcHead);
4968 pc = findNextInstruction(pc->next);
4972 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4977 /*-----------------------------------------------------------------*/
4978 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4979 /*-----------------------------------------------------------------*/
4980 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4984 for(pc = pcs; pc; pc = pc->next) {
4986 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4988 (PCI(pc)->pcop->type == PO_LABEL) &&
4989 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4996 /*-----------------------------------------------------------------*/
4997 /*-----------------------------------------------------------------*/
4998 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5005 (PCI(pc)->pcop->type == PO_LABEL)) {
5007 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5009 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5011 free(pcol->pcop.name);
5013 /* If the key is negative, then we (probably) have a label to
5014 * a function and the name is already defined */
5017 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5021 //sprintf(buffer,"_%05d_DS_",pcl->key);
5023 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5025 pcol->pcop.name = Safe_strdup(s);
5026 pcol->key = pcl->key;
5027 //pc->print(stderr,pc);
5034 /*-----------------------------------------------------------------*/
5035 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5036 /* pCode chain if they're not used. */
5037 /*-----------------------------------------------------------------*/
5038 void pBlockRemoveUnusedLabels(pBlock *pb)
5040 pCode *pc; pCodeLabel *pcl;
5045 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5047 pBranch *pbr = PCI(pc)->label;
5048 if(pbr && pbr->next) {
5049 pCode *pcd = pb->pcHead;
5051 //fprintf(stderr, "multiple labels\n");
5052 //pc->print(stderr,pc);
5057 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5058 //fprintf(stderr,"Used by:\n");
5059 //pcd->print(stderr,pcd);
5061 exchangeLabels(PCL(pbr->pc),pcd);
5070 for(pc = pb->pcHead; pc; pc = pc->next) {
5072 if(isPCL(pc)) // Label pcode
5074 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5075 pcl = PCL(PCI(pc)->label->pc);
5078 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5080 /* This pCode is a label, so search the pBlock to see if anyone
5083 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5084 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5085 /* Couldn't find an instruction that refers to this label
5086 * So, unlink the pCode label from it's pCode chain
5087 * and destroy the label */
5088 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5090 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5091 if(pc->type == PC_LABEL) {
5093 pCodeLabelDestruct(pc);
5095 unlinkpCodeFromBranch(pc, PCODE(pcl));
5096 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5107 /*-----------------------------------------------------------------*/
5108 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5109 /* chain and put them into pBranches that are */
5110 /* associated with the appropriate pCode */
5112 /*-----------------------------------------------------------------*/
5113 void pBlockMergeLabels(pBlock *pb)
5116 pCode *pc, *pcnext=NULL;
5121 /* First, Try to remove any unused labels */
5122 //pBlockRemoveUnusedLabels(pb);
5124 /* Now loop through the pBlock and merge the labels with the opcodes */
5127 // for(pc = pb->pcHead; pc; pc = pc->next) {
5130 pCode *pcn = pc->next;
5132 if(pc->type == PC_LABEL) {
5134 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5135 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5136 if((pcnext = findNextInstruction(pc) )) {
5138 // Unlink the pCode label from it's pCode chain
5141 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5142 // And link it into the instruction's pBranch labels. (Note, since
5143 // it's possible to have multiple labels associated with one instruction
5144 // we must provide a means to accomodate the additional labels. Thus
5145 // the labels are placed into the singly-linked list "label" as
5146 // opposed to being a single member of the pCodeInstruction.)
5148 //_ALLOC(pbr,sizeof(pBranch));
5149 pbr = Safe_calloc(1,sizeof(pBranch));
5153 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5156 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5158 } else if(pc->type == PC_CSOURCE) {
5160 /* merge the source line symbolic info into the next instruction */
5161 if((pcnext = findNextInstruction(pc) )) {
5163 // Unlink the pCode label from it's pCode chain
5165 PCI(pcnext)->cline = PCCS(pc);
5166 //fprintf(stderr, "merging CSRC\n");
5167 //genericPrint(stderr,pcnext);
5173 pBlockRemoveUnusedLabels(pb);
5177 /*-----------------------------------------------------------------*/
5178 /*-----------------------------------------------------------------*/
5179 int OptimizepCode(char dbName)
5181 #define MAX_PASSES 4
5190 DFPRINTF((stderr," Optimizing pCode\n"));
5194 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5195 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5196 matches += OptimizepBlock(pb);
5199 while(matches && ++passes < MAX_PASSES);
5204 /*-----------------------------------------------------------------*/
5205 /* popCopyGPR2Bit - copy a pcode operator */
5206 /*-----------------------------------------------------------------*/
5208 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5212 pcop = newpCodeOpBit(pc->name, bitval, 0);
5214 if( !( (pcop->type == PO_LABEL) ||
5215 (pcop->type == PO_LITERAL) ||
5216 (pcop->type == PO_STR) ))
5217 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5223 /*-----------------------------------------------------------------*/
5224 /*-----------------------------------------------------------------*/
5225 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5228 int firstBank = 'U';
5233 for (pc=pb->pcHead; pc; pc=pc->next) {
5235 firstBank = PCFL(pc)->firstBank;
5239 if (firstBank != 'U') {
5240 /* This block has already been done */
5241 if (firstBank != cur_bank) {
5242 /* This block has started with a different bank - must adjust it */
5243 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5246 regs *reg = getRegFromInstruction(pc);
5248 DoBankSelect(pc,cur_bank);
5258 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5261 for (pc=pb->pcHead; pc; pc=pc->next) {
5263 PCFL(pc)->firstBank = cur_bank;
5266 cur_bank = DoBankSelect(pc,cur_bank);
5269 /* Trace through branches and set the bank selection as required. */
5272 for (pc=pb->pcHead; pc; pc=pc->next) {
5274 PCFL(pc)->firstBank = cur_bank;
5278 if (PCI(pc)->op == POC_GOTO) {
5279 int lastRegIdx = LastRegIdx;
5281 /* Trace through branch */
5282 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5285 regs *reg = getRegFromInstruction(pcl);
5287 int bankUnknown = -1;
5288 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5290 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5296 LastRegIdx = lastRegIdx;
5298 /* Keep track out current bank */
5299 regs *reg = getRegFromInstruction(pc);
5301 IsBankChange(pc,reg,&cur_bank);
5308 /*-----------------------------------------------------------------*/
5309 /*-----------------------------------------------------------------*/
5310 void pBlockDestruct(pBlock *pb)
5321 /*-----------------------------------------------------------------*/
5322 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5323 /* name dbName and combine them */
5324 /* into one block */
5325 /*-----------------------------------------------------------------*/
5326 void mergepBlocks(char dbName)
5329 pBlock *pb, *pbmerged = NULL,*pbn;
5331 pb = the_pFile->pbHead;
5333 //fprintf(stderr," merging blocks named %c\n",dbName);
5337 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5338 if( getpBlock_dbName(pb) == dbName) {
5340 //fprintf(stderr," merged block %c\n",dbName);
5345 addpCode2pBlock(pbmerged, pb->pcHead);
5346 /* addpCode2pBlock doesn't handle the tail: */
5347 pbmerged->pcTail = pb->pcTail;
5349 pb->prev->next = pbn;
5351 pbn->prev = pb->prev;
5356 //printpBlock(stderr, pbmerged);
5363 /*-----------------------------------------------------------------*/
5364 /* AnalyzeFlow - Examine the flow of the code and optimize */
5366 /* level 0 == minimal optimization */
5367 /* optimize registers that are used only by two instructions */
5368 /* level 1 == maximal optimization */
5369 /* optimize by looking at pairs of instructions that use the */
5371 /*-----------------------------------------------------------------*/
5373 void AnalyzeFlow(int level)
5375 static int times_called=0;
5383 /* if this is not the first time this function has been called,
5384 then clean up old flow information */
5385 if(times_called++) {
5386 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5389 RegsUnMapLiveRanges();
5395 /* Phase 2 - Flow Analysis - Register Banking
5397 * In this phase, the individual flow blocks are examined
5398 * and register banking is fixed.
5401 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5402 //FixRegisterBanking(pb);
5404 /* Phase 2 - Flow Analysis
5406 * In this phase, the pCode is partition into pCodeFlow
5407 * blocks. The flow blocks mark the points where a continuous
5408 * stream of instructions changes flow (e.g. because of
5409 * a call or goto or whatever).
5412 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5416 /* Phase 2 - Flow Analysis - linking flow blocks
5418 * In this phase, the individual flow blocks are examined
5419 * to determine their order of excution.
5422 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5425 /* Phase 3 - Flow Analysis - Flow Tree
5427 * In this phase, the individual flow blocks are examined
5428 * to determine their order of excution.
5431 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5435 /* Phase x - Flow Analysis - Used Banks
5437 * In this phase, the individual flow blocks are examined
5438 * to determine the Register Banks they use
5441 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5445 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5446 pCodeRegMapLiveRanges(pb);
5448 RemoveUnusedRegisters();
5450 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5451 pCodeRegOptimizeRegUsage(level);
5457 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5462 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5464 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5465 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5466 pcflow = pcflow->next) {
5468 FillFlow(PCFL(pcflow));
5473 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5475 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5476 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5477 pcflow = pcflow->next) {
5479 FlowStats(PCFL(pcflow));
5485 /*-----------------------------------------------------------------*/
5486 /* AnalyzeBanking - Called after the memory addresses have been */
5487 /* assigned to the registers. */
5489 /*-----------------------------------------------------------------*/
5491 void AnalyzeBanking(void)
5495 if(!picIsInitialized()) {
5496 setDefMaxRam(); // Max RAM has not been included, so use default setting
5499 /* Phase x - Flow Analysis - Used Banks
5501 * In this phase, the individual flow blocks are examined
5502 * to determine the Register Banks they use
5508 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5509 // BanksUsedFlow(pb);
5510 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5511 FixRegisterBanking(pb,-1); // cur_bank is unknown
5515 /*-----------------------------------------------------------------*/
5516 /*-----------------------------------------------------------------*/
5517 DEFSETFUNC (resetrIdx)
5519 regs *r = (regs *)item;
5527 /*-----------------------------------------------------------------*/
5528 /* InitRegReuse - Initialises variables for code analyzer */
5529 /*-----------------------------------------------------------------*/
5531 void InitReuseReg(void)
5533 /* Find end of statically allocated variables for start idx */
5534 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5536 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5537 if (r->type != REG_SFR) {
5538 maxIdx += r->size; /* Increment for all statically allocated variables */
5542 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5545 /*-----------------------------------------------------------------*/
5546 /*-----------------------------------------------------------------*/
5547 static unsigned register_reassign(pBlock *pb, unsigned idx)
5551 /* check recursion */
5552 pc = setFirstItem(pb->function_entries);
5558 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5560 if (pb->tregisters) {
5562 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5563 if (r->type == REG_GPR) {
5565 if (r->rIdx < (int)idx) {
5568 if (peakIdx < idx) peakIdx = idx;
5569 sprintf(s,"r0x%02X", r->rIdx);
5570 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5572 r->name = Safe_strdup(s);
5578 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5580 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5581 char *dest = get_op_from_instruction(PCI(pc));
5583 pCode *pcn = findFunction(dest);
5585 register_reassign(pcn->pb,idx);
5594 /*------------------------------------------------------------------*/
5595 /* ReuseReg were call tree permits */
5597 /* Re-allocate the GPR for optimum reuse for a given pblock */
5598 /* eg if a function m() calls function f1() and f2(), where f1 */
5599 /* allocates a local variable vf1 and f2 allocates a local */
5600 /* variable vf2. Then providing f1 and f2 do not call each other */
5601 /* they may share the same general purpose registers for vf1 and */
5603 /* This is done by first setting the the regs rIdx to start after */
5604 /* all the global variables, then walking through the call tree */
5605 /* renaming the registers to match their new idx and incrementng */
5606 /* it as it goes. If a function has already been called it will */
5607 /* only rename the registers if it has already used up those */
5608 /* registers ie rIdx of the function's registers is lower than the */
5609 /* current rIdx. That way the register will not be reused while */
5610 /* still being used by an eariler function call. */
5612 /* Note for this to work the functions need to be declared static. */
5614 /*------------------------------------------------------------------*/
5619 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5620 /* Non static functions can be called from other modules so their registers must reassign */
5621 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5622 register_reassign(pb,peakIdx);
5626 /*-----------------------------------------------------------------*/
5627 /* buildCallTree - look at the flow and extract all of the calls */
5629 /*-----------------------------------------------------------------*/
5631 void buildCallTree(void )
5640 /* Now build the call tree.
5641 First we examine all of the pCodes for functions.
5642 Keep in mind that the function boundaries coincide
5643 with pBlock boundaries.
5645 The algorithm goes something like this:
5646 We have two nested loops. The outer loop iterates
5647 through all of the pBlocks/functions. The inner
5648 loop iterates through all of the pCodes for
5649 a given pBlock. When we begin iterating through
5650 a pBlock, the variable pc_fstart, pCode of the start
5651 of a function, is cleared. We then search for pCodes
5652 of type PC_FUNCTION. When one is encountered, we
5653 initialize pc_fstart to this and at the same time
5654 associate a new pBranch object that signifies a
5655 branch entry. If a return is found, then this signifies
5656 a function exit point. We'll link the pCodes of these
5657 returns to the matching pc_fstart.
5659 When we're done, a doubly linked list of pBranches
5660 will exist. The head of this list is stored in
5661 `the_pFile', which is the meta structure for all
5662 of the pCode. Look at the printCallTree function
5663 on how the pBranches are linked together.
5666 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5667 pCode *pc_fstart=NULL;
5668 for(pc = pb->pcHead; pc; pc = pc->next) {
5670 pCodeFunction *pcf = PCF(pc);
5673 if(STRCASECMP(pcf->fname, "_main") == 0) {
5674 //fprintf(stderr," found main \n");
5675 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5679 pbr = Safe_calloc(1,sizeof(pBranch));
5680 pbr->pc = pc_fstart = pc;
5683 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5685 // Here's a better way of doing the same:
5686 addSet(&pb->function_entries, pc);
5689 // Found an exit point in a function, e.g. return
5690 // (Note, there may be more than one return per function)
5692 pBranchLink(PCF(pc_fstart), pcf);
5694 addSet(&pb->function_exits, pc);
5696 } else if(isCALL(pc)) {
5697 addSet(&pb->function_calls,pc);
5703 /*-----------------------------------------------------------------*/
5704 /* AnalyzepCode - parse the pCode that has been generated and form */
5705 /* all of the logical connections. */
5707 /* Essentially what's done here is that the pCode flow is */
5709 /*-----------------------------------------------------------------*/
5711 void AnalyzepCode(char dbName)
5722 /* Phase 1 - Register allocation and peep hole optimization
5724 * The first part of the analysis is to determine the registers
5725 * that are used in the pCode. Once that is done, the peep rules
5726 * are applied to the code. We continue to loop until no more
5727 * peep rule optimizations are found (or until we exceed the
5728 * MAX_PASSES threshold).
5730 * When done, the required registers will be determined.
5736 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5738 /* First, merge the labels with the instructions */
5739 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5740 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5742 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5743 pBlockMergeLabels(pb);
5746 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5750 changes = OptimizepCode(dbName);
5752 } while(changes && (i++ < MAX_PASSES));
5757 /*-----------------------------------------------------------------*/
5758 /* ispCodeFunction - returns true if *pc is the pCode of a */
5760 /*-----------------------------------------------------------------*/
5761 bool ispCodeFunction(pCode *pc)
5764 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5770 /*-----------------------------------------------------------------*/
5771 /* findFunction - Search for a function by name (given the name) */
5772 /* in the set of all functions that are in a pBlock */
5773 /* (note - I expect this to change because I'm planning to limit */
5774 /* pBlock's to just one function declaration */
5775 /*-----------------------------------------------------------------*/
5776 pCode *findFunction(char *fname)
5783 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5785 pc = setFirstItem(pb->function_entries);
5788 if((pc->type == PC_FUNCTION) &&
5790 (strcmp(fname, PCF(pc)->fname)==0))
5793 pc = setNextItem(pb->function_entries);
5801 void MarkUsedRegisters(set *regset)
5806 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5807 r2 = pic14_regWithIdx(r1->rIdx);
5815 void pBlockStats(FILE *of, pBlock *pb)
5821 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5823 // for now just print the first element of each set
5824 pc = setFirstItem(pb->function_entries);
5826 fprintf(of,";entry: ");
5829 pc = setFirstItem(pb->function_exits);
5831 fprintf(of,";has an exit\n");
5835 pc = setFirstItem(pb->function_calls);
5837 fprintf(of,";functions called:\n");
5840 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5841 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5843 pc = setNextItem(pb->function_calls);
5847 r = setFirstItem(pb->tregisters);
5849 int n = elementsInSet(pb->tregisters);
5851 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5854 fprintf(of,"; %s\n",r->name);
5855 r = setNextItem(pb->tregisters);
5860 /*-----------------------------------------------------------------*/
5861 /*-----------------------------------------------------------------*/
5863 static void sequencepCode(void)
5869 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5871 pb->seq = GpCodeSequenceNumber+1;
5873 for( pc = pb->pcHead; pc; pc = pc->next)
5874 pc->seq = ++GpCodeSequenceNumber;
5880 /*-----------------------------------------------------------------*/
5881 /*-----------------------------------------------------------------*/
5883 set *register_usage(pBlock *pb)
5886 set *registers=NULL;
5887 set *registersInCallPath = NULL;
5889 / * check recursion * /
5891 pc = setFirstItem(pb->function_entries);
5898 if(pc->type != PC_FUNCTION)
5899 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5901 pc = setFirstItem(pb->function_calls);
5902 for( ; pc; pc = setNextItem(pb->function_calls)) {
5904 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5905 char *dest = get_op_from_instruction(PCI(pc));
5907 pcn = findFunction(dest);
5909 registersInCallPath = register_usage(pcn->pb);
5911 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5916 pBlockStats(stderr,pb); // debug
5919 // Mark the registers in this block as used.
5921 MarkUsedRegisters(pb->tregisters);
5922 if(registersInCallPath) {
5923 / * registers were used in the functions this pBlock has called * /
5924 / * so now, we need to see if these collide with the ones we are * /
5927 regs *r1,*r2, *newreg;
5929 DFPRINTF((stderr,"comparing registers\n"));
5931 r1 = setFirstItem(registersInCallPath);
5933 if (r1->type != REG_STK) {
5934 r2 = setFirstItem(pb->tregisters);
5936 while(r2 && (r2->type != REG_STK)) {
5938 if(r2->rIdx == r1->rIdx) {
5939 newreg = pic14_findFreeReg(REG_GPR);
5943 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5947 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5948 r1->rIdx, newreg->rIdx));
5949 r2->rIdx = newreg->rIdx;
5951 r2->name = Safe_strdup(newreg->name);
5955 newreg->wasUsed = 1;
5957 r2 = setNextItem(pb->tregisters);
5961 r1 = setNextItem(registersInCallPath);
5964 / * Collisions have been resolved. Now free the registers in the call path * /
5965 r1 = setFirstItem(registersInCallPath);
5967 newreg = pic14_regWithIdx(r1->rIdx);
5968 if (newreg) newreg->isFree = 1;
5969 r1 = setNextItem(registersInCallPath);
5973 // MarkUsedRegisters(pb->registers);
5975 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5978 DFPRINTF((stderr,"returning regs\n"));
5980 DFPRINTF((stderr,"not returning regs\n"));
5982 DFPRINTF((stderr,"pBlock after register optim.\n"));
5983 pBlockStats(stderr,pb); // debug
5990 /*-----------------------------------------------------------------*/
5991 /* printCallTree - writes the call tree to a file */
5993 /*-----------------------------------------------------------------*/
5994 void pct2(FILE *of,pBlock *pb,int indent)
5998 // set *registersInCallPath = NULL;
6004 return; //recursion ?
6006 pc = setFirstItem(pb->function_entries);
6013 for(i=0;i<indent;i++) // Indentation
6016 if(pc->type == PC_FUNCTION)
6017 fprintf(of,"%s\n",PCF(pc)->fname);
6022 pc = setFirstItem(pb->function_calls);
6023 for( ; pc; pc = setNextItem(pb->function_calls)) {
6025 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6026 char *dest = get_op_from_instruction(PCI(pc));
6028 pcn = findFunction(dest);
6030 pct2(of,pcn->pb,indent+1);
6032 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6040 /*-----------------------------------------------------------------*/
6041 /* printCallTree - writes the call tree to a file */
6043 /*-----------------------------------------------------------------*/
6045 void printCallTree(FILE *of)
6057 fprintf(of, "\npBlock statistics\n");
6058 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6063 fprintf(of,"Call Tree\n");
6064 pbr = the_pFile->functions;
6068 if(!ispCodeFunction(pc))
6069 fprintf(of,"bug in call tree");
6072 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6074 while(pc->next && !ispCodeFunction(pc->next)) {
6076 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6077 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6085 fprintf(of,"\n**************\n\na better call tree\n");
6086 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6091 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6092 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6098 /*-----------------------------------------------------------------*/
6100 /*-----------------------------------------------------------------*/
6102 void InlineFunction(pBlock *pb)
6110 pc = setFirstItem(pb->function_calls);
6112 for( ; pc; pc = setNextItem(pb->function_calls)) {
6115 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6116 pCode *pcp = pc->prev;
6122 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 */
6124 InlineFunction(pcn->pb);
6127 At this point, *pc points to a CALL mnemonic, and
6128 *pcn points to the function that is being called.
6130 To in-line this call, we need to remove the CALL
6131 and RETURN(s), and link the function pCode in with
6138 /* Check if previous instruction was a bit skip */
6139 if (isPCI_BITSKIP(pcp)) {
6141 /* Invert skip instruction and add a goto */
6142 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6144 if(isPCL(pc_call->next)) { // Label pcode
6145 pcl = PCL(pc_call->next);
6146 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6147 pcl = PCL(PCI(pc_call->next)->label->pc);
6149 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6150 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6152 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6155 /* remove callee pBlock from the pBlock linked list */
6156 removepBlock(pcn->pb);
6164 /* Remove the Function pCode */
6165 pct = findNextInstruction(pcn->next);
6167 /* Link the function with the callee */
6168 if (pcp) pcp->next = pcn->next;
6169 pcn->next->prev = pcp;
6171 /* Convert the function name into a label */
6173 pbr = Safe_calloc(1,sizeof(pBranch));
6174 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6176 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6177 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6179 /* turn all of the return's except the last into goto's */
6180 /* check case for 2 instruction pBlocks */
6181 pce = findNextInstruction(pcn->next);
6183 pCode *pce_next = findNextInstruction(pce->next);
6185 if(pce_next == NULL) {
6186 /* found the last return */
6187 pCode *pc_call_next = findNextInstruction(pc_call->next);
6189 //fprintf(stderr,"found last return\n");
6190 //pce->print(stderr,pce);
6191 pce->prev->next = pc_call->next;
6192 pc_call->next->prev = pce->prev;
6193 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6202 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6208 /*-----------------------------------------------------------------*/
6210 /*-----------------------------------------------------------------*/
6212 void InlinepCode(void)
6221 if(!functionInlining)
6224 /* Loop through all of the function definitions and count the
6225 * number of times each one is called */
6226 //fprintf(stderr,"inlining %d\n",__LINE__);
6228 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6230 pc = setFirstItem(pb->function_calls);
6232 for( ; pc; pc = setNextItem(pb->function_calls)) {
6235 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6236 if(pcn && isPCF(pcn)) {
6237 PCF(pcn)->ncalled++;
6240 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6245 //fprintf(stderr,"inlining %d\n",__LINE__);
6247 /* Now, Loop through the function definitions again, but this
6248 * time inline those functions that have only been called once. */
6250 InlineFunction(the_pFile->pbHead);
6251 //fprintf(stderr,"inlining %d\n",__LINE__);
6253 for(pb = the_pFile->pbHead; pb; pb = pb->next)