1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int peepOptimizing = 0; /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1; /* inline functions if nonzero */
80 int debug_verbose = 1; /* 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 == 5801)
1260 if ((pcodeId >= 855)&&(pcodeId <= 856))
1266 #ifdef HAVE_VSNPRINTF
1267 // Alas, vsnprintf is not ANSI standard, and does not exist
1268 // on Solaris (and probably other non-Gnu flavored Unixes).
1270 /*-----------------------------------------------------------------*/
1271 /* SAFE_snprintf - like snprintf except the string pointer is */
1272 /* after the string has been printed to. This is */
1273 /* useful for printing to string as though if it */
1274 /* were a stream. */
1275 /*-----------------------------------------------------------------*/
1276 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1284 va_start(val, format);
1286 vsnprintf(*str, *size, format, val);
1291 if((size_t)len > *size) {
1292 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1293 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1301 #else // HAVE_VSNPRINTF
1303 // This version is *not* safe, despite the name.
1305 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1309 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1314 va_start(val, format);
1316 vsprintf(buffer, format, val);
1319 len = strlen(buffer);
1321 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1322 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1325 strcpy(*str, buffer);
1331 #endif // HAVE_VSNPRINTF
1334 extern void initStack(int base_address, int size);
1335 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1336 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1337 extern void init_pic(char *);
1339 void pCodeInitRegisters(void)
1341 static int initialized=0;
1342 int shareBankAddress,stkSize;
1348 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1349 stkSize = 8; // Set pseudo stack size to 8
1350 initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters
1351 init_pic(port->processor);
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, 0x80);
1358 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1360 pc_status.rIdx = IDX_STATUS;
1361 pc_fsr.rIdx = IDX_FSR;
1362 pc_indf.rIdx = IDX_INDF;
1363 pc_intcon.rIdx = IDX_INTCON;
1364 pc_pcl.rIdx = IDX_PCL;
1365 pc_pclath.rIdx = IDX_PCLATH;
1367 pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1368 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1369 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1371 pc_wsave.rIdx = pc_wsave.r->rIdx;
1372 pc_ssave.rIdx = pc_ssave.r->rIdx;
1373 pc_psave.rIdx = pc_psave.r->rIdx;
1375 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1376 pc_wsave.r->address = shareBankAddress-stkSize;
1377 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1378 pc_ssave.r->address = shareBankAddress-stkSize-1;
1379 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1380 pc_psave.r->address = shareBankAddress-stkSize-2;
1382 /* probably should put this in a separate initialization routine */
1383 pb_dead_pcodes = newpBlock();
1387 /*-----------------------------------------------------------------*/
1388 /* mnem2key - convert a pic mnemonic into a hash key */
1389 /* (BTW - this spreads the mnemonics quite well) */
1391 /*-----------------------------------------------------------------*/
1393 int mnem2key(char const *mnem)
1402 key += toupper(*mnem++) +1;
1406 return (key & 0x1f);
1410 void pic14initMnemonics(void)
1415 pCodeInstruction *pci;
1417 if(mnemonics_initialized)
1420 //FIXME - probably should NULL out the array before making the assignments
1421 //since we check the array contents below this initialization.
1423 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1424 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1425 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1426 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1427 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1428 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1429 pic14Mnemonics[POC_BCF] = &pciBCF;
1430 pic14Mnemonics[POC_BSF] = &pciBSF;
1431 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1432 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1433 pic14Mnemonics[POC_CALL] = &pciCALL;
1434 pic14Mnemonics[POC_COMF] = &pciCOMF;
1435 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1436 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1437 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1438 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1439 pic14Mnemonics[POC_DECF] = &pciDECF;
1440 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1441 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1442 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1443 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1444 pic14Mnemonics[POC_INCF] = &pciINCF;
1445 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1446 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1447 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1448 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1449 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1450 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1451 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1452 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1453 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1454 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1455 pic14Mnemonics[POC_NOP] = &pciNOP;
1456 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1457 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1458 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1459 pic14Mnemonics[POC_RLF] = &pciRLF;
1460 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1461 pic14Mnemonics[POC_RRF] = &pciRRF;
1462 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1463 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1464 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1465 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1466 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1467 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1468 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1469 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1470 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1471 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1472 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1473 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1475 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1476 if(pic14Mnemonics[i])
1477 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1478 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1481 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1482 pci = hTabNextItem(pic14MnemonicsHash, &key);
1485 mnemonics_initialized = 1;
1488 int getpCodePeepCommand(char *cmd);
1490 int getpCode(char *mnem,unsigned dest)
1493 pCodeInstruction *pci;
1494 int key = mnem2key(mnem);
1496 if(!mnemonics_initialized)
1497 pic14initMnemonics();
1499 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1503 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1504 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1508 pci = hTabNextItemWK (pic14MnemonicsHash);
1515 /*-----------------------------------------------------------------*
1516 * pic14initpCodePeepCommands
1518 *-----------------------------------------------------------------*/
1519 void pic14initpCodePeepCommands(void)
1527 hTabAddItem(&pic14pCodePeepCommandsHash,
1528 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1530 } while (peepCommands[i].cmd);
1532 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1535 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1536 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1541 /*-----------------------------------------------------------------
1544 *-----------------------------------------------------------------*/
1546 int getpCodePeepCommand(char *cmd)
1550 int key = mnem2key(cmd);
1553 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1556 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1557 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1561 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1568 char getpBlock_dbName(pBlock *pb)
1574 return pb->cmemmap->dbName;
1578 void pBlockConvert2ISR(pBlock *pb)
1589 /*-----------------------------------------------------------------*/
1590 /* movepBlock2Head - given the dbname of a pBlock, move all */
1591 /* instances to the front of the doubly linked */
1592 /* list of pBlocks */
1593 /*-----------------------------------------------------------------*/
1595 void movepBlock2Head(char dbName)
1602 pb = the_pFile->pbHead;
1606 if(getpBlock_dbName(pb) == dbName) {
1607 pBlock *pbn = pb->next;
1608 pb->next = the_pFile->pbHead;
1609 the_pFile->pbHead->prev = pb;
1610 the_pFile->pbHead = pb;
1613 pb->prev->next = pbn;
1615 // If the pBlock that we just moved was the last
1616 // one in the link of all of the pBlocks, then we
1617 // need to point the tail to the block just before
1618 // the one we moved.
1619 // Note: if pb->next is NULL, then pb must have
1620 // been the last pBlock in the chain.
1623 pbn->prev = pb->prev;
1625 the_pFile->pbTail = pb->prev;
1636 void copypCode(FILE *of, char dbName)
1640 if(!of || !the_pFile)
1643 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1644 if(getpBlock_dbName(pb) == dbName) {
1652 void pcode_test(void)
1655 DFPRINTF((stderr,"pcode is alive!\n"));
1665 /* create the file name */
1666 strcpy(buffer,dstFileName);
1667 strcat(buffer,".p");
1669 if( !(pFile = fopen(buffer, "w" ))) {
1670 werror(E_FILE_OPEN_ERR,buffer);
1674 fprintf(pFile,"pcode dump\n\n");
1676 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1677 fprintf(pFile,"\n\tNew pBlock\n\n");
1679 fprintf(pFile,"%s",pb->cmemmap->sname);
1681 fprintf(pFile,"internal pblock");
1683 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1684 printpBlock(pFile,pb);
1688 /*-----------------------------------------------------------------*/
1689 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1690 /* ister, RegCond will return the bit being referenced. */
1692 /* fixme - why not just OR in the pcop bit field */
1693 /*-----------------------------------------------------------------*/
1695 static int RegCond(pCodeOp *pcop)
1701 if (pcop->type == PO_GPR_BIT) {
1702 char *name = pcop->name;
1704 name = PCOR(pcop)->r->name;
1705 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1706 switch(PCORB(pcop)->bit) {
1720 /*-----------------------------------------------------------------*/
1721 /* newpCode - create and return a newly initialized pCode */
1723 /* fixme - rename this */
1725 /* The purpose of this routine is to create a new Instruction */
1726 /* pCode. This is called by gen.c while the assembly code is being */
1730 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1731 /* (note that the op is analogous to but not the */
1732 /* same thing as the opcode of the instruction.) */
1733 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1736 /* a pointer to the new malloc'd pCode is returned. */
1740 /*-----------------------------------------------------------------*/
1741 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1743 pCodeInstruction *pci ;
1745 if(!mnemonics_initialized)
1746 pic14initMnemonics();
1748 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1750 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1751 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1752 pci->pc.id = PCodeID();
1755 if(pci->inCond & PCC_EXAMINE_PCOP)
1756 pci->inCond |= RegCond(pcop);
1758 if(pci->outCond & PCC_EXAMINE_PCOP)
1759 pci->outCond |= RegCond(pcop);
1761 pci->pc.prev = pci->pc.next = NULL;
1762 return (pCode *)pci;
1765 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1771 /*-----------------------------------------------------------------*/
1772 /* newpCodeWild - create a "wild" as in wild card pCode */
1774 /* Wild pcodes are used during the peep hole optimizer to serve */
1775 /* as place holders for any instruction. When a snippet of code is */
1776 /* compared to a peep hole rule, the wild card opcode will match */
1777 /* any instruction. However, the optional operand and label are */
1778 /* additional qualifiers that must also be matched before the */
1779 /* line (of assembly code) is declared matched. Note that the */
1780 /* operand may be wild too. */
1782 /* Note, a wild instruction is specified just like a wild var: */
1783 /* %4 ; A wild instruction, */
1784 /* See the peeph.def file for additional examples */
1786 /*-----------------------------------------------------------------*/
1788 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1793 pcw = Safe_calloc(1,sizeof(pCodeWild));
1795 pcw->pci.pc.type = PC_WILD;
1796 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1797 pcw->id = PCodeID();
1798 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1799 pcw->pci.pc.pb = NULL;
1801 // pcw->pci.pc.analyze = genericAnalyze;
1802 pcw->pci.pc.destruct = genericDestruct;
1803 pcw->pci.pc.print = genericPrint;
1805 pcw->id = pCodeID; // this is the 'n' in %n
1806 pcw->operand = optional_operand;
1807 pcw->label = optional_label;
1809 pcw->mustBeBitSkipInst = 0;
1810 pcw->mustNotBeBitSkipInst = 0;
1811 pcw->invertBitSkipInst = 0;
1813 return ( (pCode *)pcw);
1817 /*-----------------------------------------------------------------*/
1818 /* newPcodeInlineP - create a new pCode from a char string */
1819 /*-----------------------------------------------------------------*/
1822 pCode *newpCodeInlineP(char *cP)
1827 pcc = Safe_calloc(1,sizeof(pCodeComment));
1829 pcc->pc.type = PC_INLINE;
1830 pcc->pc.prev = pcc->pc.next = NULL;
1831 pcc->pc.id = PCodeID();
1832 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1835 // pcc->pc.analyze = genericAnalyze;
1836 pcc->pc.destruct = genericDestruct;
1837 pcc->pc.print = genericPrint;
1840 pcc->comment = Safe_strdup(cP);
1842 pcc->comment = NULL;
1844 return ( (pCode *)pcc);
1848 /*-----------------------------------------------------------------*/
1849 /* newPcodeCharP - create a new pCode from a char string */
1850 /*-----------------------------------------------------------------*/
1852 pCode *newpCodeCharP(char *cP)
1857 pcc = Safe_calloc(1,sizeof(pCodeComment));
1859 pcc->pc.type = PC_COMMENT;
1860 pcc->pc.prev = pcc->pc.next = NULL;
1861 pcc->pc.id = PCodeID();
1862 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1865 // pcc->pc.analyze = genericAnalyze;
1866 pcc->pc.destruct = genericDestruct;
1867 pcc->pc.print = genericPrint;
1870 pcc->comment = Safe_strdup(cP);
1872 pcc->comment = NULL;
1874 return ( (pCode *)pcc);
1878 /*-----------------------------------------------------------------*/
1879 /* newpCodeFunction - */
1880 /*-----------------------------------------------------------------*/
1883 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1887 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1888 //_ALLOC(pcf,sizeof(pCodeFunction));
1890 pcf->pc.type = PC_FUNCTION;
1891 pcf->pc.prev = pcf->pc.next = NULL;
1892 pcf->pc.id = PCodeID();
1893 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1896 // pcf->pc.analyze = genericAnalyze;
1897 pcf->pc.destruct = genericDestruct;
1898 pcf->pc.print = pCodePrintFunction;
1903 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1904 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1905 strcpy(pcf->modname,mod);
1907 pcf->modname = NULL;
1910 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1911 pcf->fname = Safe_calloc(1,strlen(f)+1);
1912 strcpy(pcf->fname,f);
1916 pcf->isPublic = (unsigned)isPublic;
1918 return ( (pCode *)pcf);
1922 /*-----------------------------------------------------------------*/
1924 /*-----------------------------------------------------------------*/
1925 void destructpCodeFlow(pCode *pc)
1927 if(!pc || !isPCFL(pc))
1936 deleteSet(&PCFL(pc)->registers);
1937 deleteSet(&PCFL(pc)->from);
1938 deleteSet(&PCFL(pc)->to);
1943 pCode *newpCodeFlow(void )
1947 //_ALLOC(pcflow,sizeof(pCodeFlow));
1948 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1950 pcflow->pc.type = PC_FLOW;
1951 pcflow->pc.prev = pcflow->pc.next = NULL;
1952 pcflow->pc.pb = NULL;
1954 // pcflow->pc.analyze = genericAnalyze;
1955 pcflow->pc.destruct = destructpCodeFlow;
1956 pcflow->pc.print = genericPrint;
1958 pcflow->pc.seq = GpcFlowSeq++;
1960 pcflow->from = pcflow->to = NULL;
1962 pcflow->inCond = PCC_NONE;
1963 pcflow->outCond = PCC_NONE;
1965 pcflow->firstBank = 'U'; /* Undetermined */
1966 pcflow->lastBank = 'U'; /* Undetermined */
1968 pcflow->FromConflicts = 0;
1969 pcflow->ToConflicts = 0;
1973 pcflow->registers = newSet();
1975 return ( (pCode *)pcflow);
1979 /*-----------------------------------------------------------------*/
1980 /*-----------------------------------------------------------------*/
1981 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1983 pCodeFlowLink *pcflowLink;
1985 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1987 pcflowLink->pcflow = pcflow;
1988 pcflowLink->bank_conflict = 0;
1993 /*-----------------------------------------------------------------*/
1994 /* newpCodeCSource - create a new pCode Source Symbol */
1995 /*-----------------------------------------------------------------*/
1997 pCode *newpCodeCSource(int ln, char *f, char *l)
2002 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2004 pccs->pc.type = PC_CSOURCE;
2005 pccs->pc.prev = pccs->pc.next = NULL;
2006 pccs->pc.id = PCodeID();
2009 pccs->pc.destruct = genericDestruct;
2010 pccs->pc.print = genericPrint;
2012 pccs->line_number = ln;
2014 pccs->line = Safe_strdup(l);
2019 pccs->file_name = Safe_strdup(f);
2021 pccs->file_name = NULL;
2023 return ( (pCode *)pccs);
2026 /*-----------------------------------------------------------------*/
2027 /* pCodeLabelDestruct - free memory used by a label. */
2028 /*-----------------------------------------------------------------*/
2029 static void pCodeLabelDestruct(pCode *pc)
2035 if((pc->type == PC_LABEL) && PCL(pc)->label)
2036 free(PCL(pc)->label);
2042 pCode *newpCodeLabel(char *name, int key)
2048 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2050 pcl->pc.type = PC_LABEL;
2051 pcl->pc.prev = pcl->pc.next = NULL;
2052 pcl->pc.id = PCodeID();
2053 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2056 // pcl->pc.analyze = genericAnalyze;
2057 pcl->pc.destruct = pCodeLabelDestruct;
2058 pcl->pc.print = pCodePrintLabel;
2064 sprintf(s,"_%05d_DS_",key);
2069 pcl->label = Safe_strdup(s);
2071 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2072 return ( (pCode *)pcl);
2077 /*-----------------------------------------------------------------*/
2078 /* newpBlock - create and return a pointer to a new pBlock */
2079 /*-----------------------------------------------------------------*/
2080 pBlock *newpBlock(void)
2085 PpB = Safe_calloc(1,sizeof(pBlock) );
2086 PpB->next = PpB->prev = NULL;
2088 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2089 PpB->tregisters = NULL;
2091 PpB->FlowTree = NULL;
2097 /*-----------------------------------------------------------------*/
2098 /* newpCodeChain - create a new chain of pCodes */
2099 /*-----------------------------------------------------------------*
2101 * This function will create a new pBlock and the pointer to the
2102 * pCode that is passed in will be the first pCode in the block.
2103 *-----------------------------------------------------------------*/
2106 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2109 pBlock *pB = newpBlock();
2111 pB->pcHead = pB->pcTail = pc;
2118 /*-----------------------------------------------------------------*/
2119 /* newpCodeOpLabel - Create a new label given the key */
2120 /* Note, a negative key means that the label is part of wild card */
2121 /* (and hence a wild card label) used in the pCodePeep */
2122 /* optimizations). */
2123 /*-----------------------------------------------------------------*/
2125 pCodeOp *newpCodeOpLabel(char *name, int key)
2128 static int label_key=-1;
2132 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2133 pcop->type = PO_LABEL;
2138 sprintf(s=buffer,"_%05d_DS_",key);
2140 s = name, key = label_key--;
2142 PCOLAB(pcop)->offset = 0;
2144 pcop->name = Safe_strdup(s);
2146 ((pCodeOpLabel *)pcop)->key = key;
2148 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2152 /*-----------------------------------------------------------------*/
2153 /*-----------------------------------------------------------------*/
2154 pCodeOp *newpCodeOpLit(int lit)
2160 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2161 pcop->type = PO_LITERAL;
2165 sprintf(s,"0x%02x",lit);
2167 pcop->name = Safe_strdup(s);
2170 ((pCodeOpLit *)pcop)->lit = lit;
2175 /*-----------------------------------------------------------------*/
2176 /*-----------------------------------------------------------------*/
2177 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2181 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2182 pcop->type = PO_IMMEDIATE;
2185 pcop->name = Safe_strdup(name);
2188 r = dirregWithName(name);
2192 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2193 PCOI(pcop)->rIdx = r->rIdx;
2195 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2196 PCOI(pcop)->rIdx = -1;
2198 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2203 PCOI(pcop)->index = index;
2204 PCOI(pcop)->offset = offset;
2205 PCOI(pcop)->_const = code_space;
2206 PCOI(pcop)->_function = is_func;
2211 /*-----------------------------------------------------------------*/
2212 /*-----------------------------------------------------------------*/
2213 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2219 if(!pcwb || !subtype) {
2220 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2224 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2225 pcop->type = PO_WILD;
2226 sprintf(s,"%%%d",id);
2227 pcop->name = Safe_strdup(s);
2229 PCOW(pcop)->id = id;
2230 PCOW(pcop)->pcwb = pcwb;
2231 PCOW(pcop)->subtype = subtype;
2232 PCOW(pcop)->matched = NULL;
2236 /*-----------------------------------------------------------------*/
2237 /* Find a symbol with matching name */
2238 /*-----------------------------------------------------------------*/
2239 static symbol *symFindWithName(memmap * map, const char *name)
2243 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2244 if (sym->rname && (strcmp(sym->rname,name)==0))
2250 /*-----------------------------------------------------------------*/
2251 /*-----------------------------------------------------------------*/
2252 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2257 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2258 pcop->type = PO_GPR_BIT;
2260 PCORB(pcop)->bit = ibit;
2261 PCORB(pcop)->inBitSpace = inBitSpace;
2263 if (name) r = regFindWithName(name);
2265 // Register has not been allocated - check for symbol information
2267 sym = symFindWithName(bit, name);
2268 if (!sym) sym = symFindWithName(sfrbit, name);
2269 if (!sym) sym = symFindWithName(sfr, name);
2271 r = allocNewDirReg(sym->etype,name);
2277 PCOR(pcop)->rIdx = r->rIdx;
2279 pcop->name = Safe_strdup(name);
2280 PCOR(pcop)->r = NULL;
2281 PCOR(pcop)->rIdx = 0;
2286 /*-----------------------------------------------------------------*
2287 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2289 * If rIdx >=0 then a specific register from the set of registers
2290 * will be selected. If rIdx <0, then a new register will be searched
2292 *-----------------------------------------------------------------*/
2294 pCodeOp *newpCodeOpReg(int rIdx)
2298 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2303 PCOR(pcop)->rIdx = rIdx;
2304 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2306 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2309 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2313 pcop->type = PCOR(pcop)->r->pc_type;
2318 pCodeOp *newpCodeOpRegFromStr(char *name)
2322 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2323 PCOR(pcop)->r = allocRegByName(name, 1);
2324 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2325 pcop->type = PCOR(pcop)->r->pc_type;
2326 pcop->name = PCOR(pcop)->r->name;
2331 pCodeOp *newpCodeOpStr(char *name)
2335 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2336 pcop->type = PO_STR;
2337 pcop->name = Safe_strdup(name);
2339 PCOS(pcop)->isPublic = 0;
2345 /*-----------------------------------------------------------------*/
2346 /*-----------------------------------------------------------------*/
2348 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2355 pcop = newpCodeOpBit(name, -1,0);
2359 pcop = newpCodeOpLit(-1);
2363 pcop = newpCodeOpLabel(NULL,-1);
2367 pcop = newpCodeOpReg(-1);
2370 case PO_GPR_POINTER:
2371 case PO_GPR_REGISTER:
2373 pcop = newpCodeOpRegFromStr(name);
2375 pcop = newpCodeOpReg(-1);
2379 pcop = newpCodeOpStr(name);
2383 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2386 pcop->name = Safe_strdup(name);
2394 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2396 void pCodeConstString(char *name, char *value)
2400 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2405 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2409 sprintf(buffer,"; %s = %s",name,value);
2411 addpCode2pBlock(pb,newpCodeCharP(buffer));
2412 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2415 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2421 /*-----------------------------------------------------------------*/
2422 /*-----------------------------------------------------------------*/
2423 void pCodeReadCodeTable(void)
2427 fprintf(stderr, " %s\n",__FUNCTION__);
2429 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2433 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2434 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2435 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2436 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2438 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2439 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2440 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2441 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2446 /*-----------------------------------------------------------------*/
2447 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2448 /*-----------------------------------------------------------------*/
2449 void addpCode2pBlock(pBlock *pb, pCode *pc)
2456 /* If this is the first pcode to be added to a block that
2457 * was initialized with a NULL pcode, then go ahead and
2458 * make this pcode the head and tail */
2459 pb->pcHead = pb->pcTail = pc;
2462 pb->pcTail->next = pc;
2464 pc->prev = pb->pcTail;
2471 /*-----------------------------------------------------------------*/
2472 /* addpBlock - place a pBlock into the pFile */
2473 /*-----------------------------------------------------------------*/
2474 void addpBlock(pBlock *pb)
2476 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2479 /* First time called, we'll pass through here. */
2480 //_ALLOC(the_pFile,sizeof(pFile));
2481 the_pFile = Safe_calloc(1,sizeof(pFile));
2482 the_pFile->pbHead = the_pFile->pbTail = pb;
2483 the_pFile->functions = NULL;
2487 the_pFile->pbTail->next = pb;
2488 pb->prev = the_pFile->pbTail;
2490 the_pFile->pbTail = pb;
2493 /*-----------------------------------------------------------------*/
2494 /* removepBlock - remove a pBlock from the pFile */
2495 /*-----------------------------------------------------------------*/
2496 void removepBlock(pBlock *pb)
2504 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2506 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2509 if(pbs == the_pFile->pbHead)
2510 the_pFile->pbHead = pbs->next;
2512 if (pbs == the_pFile->pbTail)
2513 the_pFile->pbTail = pbs->prev;
2516 pbs->next->prev = pbs->prev;
2519 pbs->prev->next = pbs->next;
2526 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2530 /*-----------------------------------------------------------------*/
2531 /* printpCode - write the contents of a pCode to a file */
2532 /*-----------------------------------------------------------------*/
2533 void printpCode(FILE *of, pCode *pc)
2544 fprintf(of,"warning - unable to print pCode\n");
2547 /*-----------------------------------------------------------------*/
2548 /* printpBlock - write the contents of a pBlock to a file */
2549 /*-----------------------------------------------------------------*/
2550 void printpBlock(FILE *of, pBlock *pb)
2560 for(pc = pb->pcHead; pc; pc = pc->next)
2565 /*-----------------------------------------------------------------*/
2567 /* pCode processing */
2571 /*-----------------------------------------------------------------*/
2573 void unlinkpCode(pCode *pc)
2579 fprintf(stderr,"Unlinking: ");
2580 printpCode(stderr, pc);
2583 pc->prev->next = pc->next;
2585 pc->next->prev = pc->prev;
2587 pc->prev = pc->next = NULL;
2591 /*-----------------------------------------------------------------*/
2592 /*-----------------------------------------------------------------*/
2594 static void genericDestruct(pCode *pc)
2600 /* For instructions, tell the register (if there's one used)
2601 * that it's no longer needed */
2602 regs *reg = getRegFromInstruction(pc);
2604 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2607 /* Instead of deleting the memory used by this pCode, mark
2608 * the object as bad so that if there's a pointer to this pCode
2609 * dangling around somewhere then (hopefully) when the type is
2610 * checked we'll catch it.
2615 addpCode2pBlock(pb_dead_pcodes, pc);
2622 /*-----------------------------------------------------------------*/
2623 /* Copies the pCodeInstruction flow pointer from source pCode */
2624 /*-----------------------------------------------------------------*/
2625 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2627 pCodeFlow *pcflow = 0;
2628 for (p=pcs; p; p=p->prev) {
2630 pcflow = PCI(p)->pcflow;
2634 pcflow = (pCodeFlow*)p;
2638 PCI(pcd)->pcflow = pcflow;
2641 /*-----------------------------------------------------------------*/
2642 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2643 /* into the pCode chain containing pc1 */
2644 /*-----------------------------------------------------------------*/
2645 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2651 pc2->next = pc1->next;
2653 pc1->next->prev = pc2;
2659 /* If this is an instrution type propogate the flow */
2661 CopyFlow(PCI(pc2),pc1);
2664 /*------------------------------------------------------------------*/
2665 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2666 /* into the pCode chain containing pc1 */
2667 /*------------------------------------------------------------------*/
2668 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2674 pc2->prev = pc1->prev;
2676 pc1->prev->next = pc2;
2682 /* If this is an instrution type propogate the flow */
2684 CopyFlow(PCI(pc2),pc1);
2687 /*-----------------------------------------------------------------*/
2688 /* pCodeOpCopy - copy a pcode operator */
2689 /*-----------------------------------------------------------------*/
2690 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2692 pCodeOp *pcopnew=NULL;
2697 switch(pcop->type) {
2700 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2701 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2702 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2703 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2708 /* Here we expand the wild card into the appropriate type: */
2709 /* By recursively calling pCodeOpCopy */
2710 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2711 if(PCOW(pcop)->matched)
2712 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2715 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2716 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2717 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2724 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2725 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2726 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2730 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2731 PCOI(pcopnew)->index = PCOI(pcop)->index;
2732 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2733 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2734 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2738 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2739 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2740 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2745 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2746 PCOR(pcopnew)->r = PCOR(pcop)->r;
2747 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2748 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2752 case PO_GPR_POINTER:
2753 case PO_GPR_REGISTER:
2757 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2758 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2759 PCOR(pcopnew)->r = PCOR(pcop)->r;
2760 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2761 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2762 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2766 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2767 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2768 PCOR(pcopnew)->r = PCOR(pcop)->r;
2769 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2770 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2773 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2774 case PO_SFR_REGISTER:
2782 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2783 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2787 pcopnew->type = pcop->type;
2789 pcopnew->name = Safe_strdup(pcop->name);
2791 pcopnew->name = NULL;
2796 /*-----------------------------------------------------------------*/
2797 /* popCopyReg - copy a pcode operator */
2798 /*-----------------------------------------------------------------*/
2799 pCodeOp *popCopyReg(pCodeOpReg *pc)
2803 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2804 pcor->pcop.type = pc->pcop.type;
2806 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2807 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2809 pcor->pcop.name = NULL;
2812 pcor->rIdx = pc->rIdx;
2815 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2820 /*-----------------------------------------------------------------*/
2821 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2822 /*-----------------------------------------------------------------*/
2823 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2825 pCodeInstruction *new_pci;
2828 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2830 new_pci = PCI(newpCode(pci->op,pci->pcop));
2832 new_pci->pc.pb = pci->pc.pb;
2833 new_pci->from = pci->from;
2834 new_pci->to = pci->to;
2835 new_pci->label = pci->label;
2836 new_pci->pcflow = pci->pcflow;
2838 return PCODE(new_pci);
2841 /*-----------------------------------------------------------------*/
2842 /*-----------------------------------------------------------------*/
2843 void pCodeDeleteChain(pCode *f,pCode *t)
2848 DFPRINTF((stderr,"delete pCode:\n"));
2850 //f->print(stderr,f);
2851 //f->delete(f); this dumps core...
2856 /*-----------------------------------------------------------------*/
2857 /*-----------------------------------------------------------------*/
2858 void pBlockRegs(FILE *of, pBlock *pb)
2863 r = setFirstItem(pb->tregisters);
2865 r = setNextItem(pb->tregisters);
2870 /*-----------------------------------------------------------------*/
2871 /*-----------------------------------------------------------------*/
2872 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2877 int use_buffer = 1; // copy the string to the passed buffer pointer
2882 use_buffer = 0; // Don't bother copying the string to the buffer.
2886 switch(pcop->type) {
2890 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2893 //return PCOR(pcop)->r->name;
2897 if (PCOR(pcop)->r->type == REG_STK)
2898 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2900 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2903 SAFE_snprintf(&buffer,&size,"%s",r->name);
2913 if(PCOI(pcop)->_const) {
2915 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2916 switch(PCOI(pcop)->offset) {
2918 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2921 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2924 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2927 8 * PCOI(pcop)->offset );
2930 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2933 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2934 SAFE_snprintf(&s,&size,"(%s + %d)",
2936 PCOI(pcop)->index );
2938 switch(PCOI(pcop)->offset) {
2940 SAFE_snprintf(&s,&size,"%s",pcop->name);
2943 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2946 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2955 //size = sizeof(buffer);
2956 if( PCOR(pcop)->instance) {
2957 SAFE_snprintf(&s,&size,"(%s + %d)",
2959 PCOR(pcop)->instance );
2960 //fprintf(stderr,"PO_DIR %s\n",buffer);
2962 SAFE_snprintf(&s,&size,"%s",pcop->name);
2968 if(PCOLAB(pcop)->offset == 1)
2969 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2971 SAFE_snprintf(&s,&size,"%s",pcop->name);
2978 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2981 return PCOR(pcop)->r->name;
2984 /* fall through to the default case */
2988 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2996 printf("PIC port internal warning: (%s:%d) %s not found\n",
3001 return "NO operand";
3005 /*-----------------------------------------------------------------*/
3006 /*-----------------------------------------------------------------*/
3007 static char *get_op_from_instruction( pCodeInstruction *pcc)
3011 return get_op(pcc->pcop,NULL,0);
3013 return ("ERROR Null: get_op_from_instruction");
3017 /*-----------------------------------------------------------------*/
3018 /*-----------------------------------------------------------------*/
3019 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3021 fprintf(of,"pcodeopprint- not implemented\n");
3024 /*-----------------------------------------------------------------*/
3025 /*-----------------------------------------------------------------*/
3026 char *pCode2str(char *str, size_t size, pCode *pc)
3034 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3036 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3038 if(PCI(pc)->isBitInst) {
3039 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3040 char *name = PCI(pc)->pcop->name;
3042 name = PCOR(PCI(pc)->pcop)->r->name;
3043 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3044 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3046 SAFE_snprintf(&s,&size,"%s,%d", name,
3047 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3048 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3049 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3051 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3052 //PCI(pc)->pcop->t.bit );
3055 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3056 if( PCI(pc)->num_ops == 2)
3057 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3059 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3062 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3064 if( PCI(pc)->num_ops == 2)
3065 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3073 /* assuming that comment ends with a \n */
3074 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3078 /* assuming that inline code ends with a \n */
3079 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3083 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3086 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3089 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3092 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3095 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3099 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3106 /*-----------------------------------------------------------------*/
3107 /* genericPrint - the contents of a pCode to a file */
3108 /*-----------------------------------------------------------------*/
3109 static void genericPrint(FILE *of, pCode *pc)
3117 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3121 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3125 // If the opcode has a label, print that first
3127 pBranch *pbl = PCI(pc)->label;
3128 while(pbl && pbl->pc) {
3129 if(pbl->pc->type == PC_LABEL)
3130 pCodePrintLabel(of, pbl->pc);
3136 genericPrint(of,PCODE(PCI(pc)->cline));
3141 pCode2str(str, 256, pc);
3143 fprintf(of,"%s",str);
3147 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3149 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3154 pBranch *dpb = pc->to; // debug
3156 switch ( dpb->pc->type) {
3158 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3161 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3164 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3167 fprintf(of, "\t;flow");
3181 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3182 if(PCW(pc)->pci.label)
3183 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3185 if(PCW(pc)->operand) {
3186 fprintf(of,";\toperand ");
3187 pCodeOpPrint(of,PCW(pc)->operand );
3193 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3194 if(PCFL(pc)->ancestor)
3195 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3202 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3206 fprintf(of,"unknown pCode type %d\n",pc->type);
3211 /*-----------------------------------------------------------------*/
3212 /* pCodePrintFunction - prints function begin/end */
3213 /*-----------------------------------------------------------------*/
3215 static void pCodePrintFunction(FILE *of, pCode *pc)
3221 if( ((pCodeFunction *)pc)->modname)
3222 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3224 if(PCF(pc)->fname) {
3225 pBranch *exits = PCF(pc)->to;
3227 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3230 exits = exits->next;
3233 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3236 if((PCF(pc)->from &&
3237 PCF(pc)->from->pc->type == PC_FUNCTION &&
3238 PCF(PCF(pc)->from->pc)->fname) )
3239 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3241 fprintf(of,"; exit point [can't find entry point]\n");
3244 /*-----------------------------------------------------------------*/
3245 /* pCodePrintLabel - prints label */
3246 /*-----------------------------------------------------------------*/
3248 static void pCodePrintLabel(FILE *of, pCode *pc)
3255 fprintf(of,"%s\n",PCL(pc)->label);
3256 else if (PCL(pc)->key >=0)
3257 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3259 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3262 /*-----------------------------------------------------------------*/
3263 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3264 /* remove it if it is found. */
3265 /*-----------------------------------------------------------------*/
3266 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3273 if(pcl->type == PC_OPCODE)
3274 b = PCI(pcl)->label;
3276 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3281 //fprintf (stderr, "%s \n",__FUNCTION__);
3282 //pcl->print(stderr,pcl);
3283 //pc->print(stderr,pc);
3286 //fprintf (stderr, "found label\n");
3290 bprev->next = b->next; /* Not first pCode in chain */
3294 PCI(pcl)->label = b->next; /* First pCode in chain */
3297 return; /* A label can't occur more than once */
3305 /*-----------------------------------------------------------------*/
3306 /*-----------------------------------------------------------------*/
3307 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3326 /*-----------------------------------------------------------------*/
3327 /* pBranchLink - given two pcodes, this function will link them */
3328 /* together through their pBranches */
3329 /*-----------------------------------------------------------------*/
3330 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3334 // Declare a new branch object for the 'from' pCode.
3336 //_ALLOC(b,sizeof(pBranch));
3337 b = Safe_calloc(1,sizeof(pBranch));
3338 b->pc = PCODE(t); // The link to the 'to' pCode.
3341 f->to = pBranchAppend(f->to,b);
3343 // Now do the same for the 'to' pCode.
3345 //_ALLOC(b,sizeof(pBranch));
3346 b = Safe_calloc(1,sizeof(pBranch));
3350 t->from = pBranchAppend(t->from,b);
3355 /*-----------------------------------------------------------------*/
3356 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3358 /*-----------------------------------------------------------------*/
3359 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3372 /*-----------------------------------------------------------------*/
3373 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3374 /*-----------------------------------------------------------------*/
3375 static void pCodeUnlink(pCode *pc)
3380 if(!pc->prev || !pc->next) {
3381 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3385 /* first remove the pCode from the chain */
3386 pc->prev->next = pc->next;
3387 pc->next->prev = pc->prev;
3389 /* Now for the hard part... */
3391 /* Remove the branches */
3395 pc1 = pb1->pc; /* Get the pCode that branches to the
3396 * one we're unlinking */
3398 /* search for the link back to this pCode (the one we're
3400 if(pb2 = pBranchFind(pc1->to,pc)) {
3401 pb2->pc = pc->to->pc; // make the replacement
3403 /* if the pCode we're unlinking contains multiple 'to'
3404 * branches (e.g. this a skip instruction) then we need
3405 * to copy these extra branches to the chain. */
3407 pBranchAppend(pb2, pc->to->next);
3416 /*-----------------------------------------------------------------*/
3417 /*-----------------------------------------------------------------*/
3419 static void genericAnalyze(pCode *pc)
3429 // Go through the pCodes that are in pCode chain and link
3430 // them together through the pBranches. Note, the pCodes
3431 // are linked together as a contiguous stream like the
3432 // assembly source code lines. The linking here mimics this
3433 // except that comments are not linked in.
3435 pCode *npc = pc->next;
3437 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3438 pBranchLink(pc,npc);
3443 /* reached the end of the pcode chain without finding
3444 * an instruction we could link to. */
3448 fprintf(stderr,"analyze PC_FLOW\n");
3452 fprintf(stderr,";A bad pCode is being used\n");
3458 /*-----------------------------------------------------------------*/
3459 /*-----------------------------------------------------------------*/
3460 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3464 if(pc->type == PC_LABEL) {
3465 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3468 if(pc->type == PC_OPCODE) {
3469 pbr = PCI(pc)->label;
3471 if(pbr->pc->type == PC_LABEL) {
3472 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3482 /*-----------------------------------------------------------------*/
3483 /*-----------------------------------------------------------------*/
3484 int checkLabel(pCode *pc)
3488 if(pc && isPCI(pc)) {
3489 pbr = PCI(pc)->label;
3491 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3501 /*-----------------------------------------------------------------*/
3502 /* findLabelinpBlock - Search the pCode for a particular label */
3503 /*-----------------------------------------------------------------*/
3504 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3511 for(pc = pb->pcHead; pc; pc = pc->next)
3512 if(compareLabel(pc,pcop_label))
3518 /*-----------------------------------------------------------------*/
3519 /* findLabel - Search the pCode for a particular label */
3520 /*-----------------------------------------------------------------*/
3521 pCode * findLabel(pCodeOpLabel *pcop_label)
3529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3530 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3534 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3538 /*-----------------------------------------------------------------*/
3539 /* findNextpCode - given a pCode, find the next of type 'pct' */
3540 /* in the linked list */
3541 /*-----------------------------------------------------------------*/
3542 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3555 /*-----------------------------------------------------------------*/
3556 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3557 /* in the linked list */
3558 /*-----------------------------------------------------------------*/
3559 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3571 /*-----------------------------------------------------------------*/
3572 /* findNextInstruction - given a pCode, find the next instruction */
3573 /* in the linked list */
3574 /*-----------------------------------------------------------------*/
3575 pCode * findNextInstruction(pCode *pci)
3580 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3584 fprintf(stderr,"findNextInstruction: ");
3585 printpCode(stderr, pc);
3590 //fprintf(stderr,"Couldn't find instruction\n");
3594 /*-----------------------------------------------------------------*/
3595 /* findNextInstruction - given a pCode, find the next instruction */
3596 /* in the linked list */
3597 /*-----------------------------------------------------------------*/
3598 pCode * findPrevInstruction(pCode *pci)
3600 return findPrevpCode(pci, PC_OPCODE);
3603 /*-----------------------------------------------------------------*/
3604 /* findFunctionEnd - given a pCode find the end of the function */
3605 /* that contains it */
3606 /*-----------------------------------------------------------------*/
3607 pCode * findFunctionEnd(pCode *pc)
3611 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3617 fprintf(stderr,"Couldn't find function end\n");
3622 /*-----------------------------------------------------------------*/
3623 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3624 /* instruction with which it is associated. */
3625 /*-----------------------------------------------------------------*/
3626 static void AnalyzeLabel(pCode *pc)
3635 static void AnalyzeGOTO(pCode *pc)
3638 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3642 static void AnalyzeSKIP(pCode *pc)
3645 pBranchLink(pc,findNextInstruction(pc->next));
3646 pBranchLink(pc,findNextInstruction(pc->next->next));
3650 static void AnalyzeRETURN(pCode *pc)
3653 // branch_link(pc,findFunctionEnd(pc->next));
3659 /*-----------------------------------------------------------------*/
3660 /*-----------------------------------------------------------------*/
3661 regs * getRegFromInstruction(pCode *pc)
3667 PCI(pc)->num_ops == 0 )
3670 switch(PCI(pc)->pcop->type) {
3673 return PCOR(PCI(pc)->pcop)->r;
3675 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3679 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3680 return PCOR(PCI(pc)->pcop)->r;
3683 if(PCOI(PCI(pc)->pcop)->r)
3684 return (PCOI(PCI(pc)->pcop)->r);
3686 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3687 return dirregWithName(PCI(pc)->pcop->name);
3688 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3691 return PCOR(PCI(pc)->pcop)->r;
3693 case PO_GPR_REGISTER:
3695 //fprintf(stderr, "getRegFromInstruction - dir\n");
3696 return PCOR(PCI(pc)->pcop)->r;
3698 //fprintf(stderr, "getRegFromInstruction - literal\n");
3702 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3703 //genericPrint(stderr, pc);
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3714 void AnalyzepBlock(pBlock *pb)
3721 /* Find all of the registers used in this pBlock
3722 * by looking at each instruction and examining it's
3725 for(pc = pb->pcHead; pc; pc = pc->next) {
3727 /* Is this an instruction with operands? */
3728 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3730 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3731 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3733 /* Loop through all of the registers declared so far in
3734 this block and see if we find this one there */
3736 regs *r = setFirstItem(pb->tregisters);
3739 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3740 PCOR(PCI(pc)->pcop)->r = r;
3743 r = setNextItem(pb->tregisters);
3747 /* register wasn't found */
3748 //r = Safe_calloc(1, sizeof(regs));
3749 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3750 //addSet(&pb->tregisters, r);
3751 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3752 //PCOR(PCI(pc)->pcop)->r = r;
3753 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3755 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3758 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3759 if(PCOR(PCI(pc)->pcop)->r) {
3760 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3761 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3763 if(PCI(pc)->pcop->name)
3764 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3766 fprintf(stderr,"ERROR: NULL register\n");
3775 /*-----------------------------------------------------------------*/
3777 /*-----------------------------------------------------------------*/
3778 void InsertpFlow(pCode *pc, pCode **pflow)
3781 PCFL(*pflow)->end = pc;
3783 if(!pc || !pc->next)
3786 *pflow = newpCodeFlow();
3787 pCodeInsertAfter(pc, *pflow);
3790 /*-----------------------------------------------------------------*/
3791 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3792 /* the flow blocks. */
3794 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3795 * point the instruction flow changes.
3797 /*-----------------------------------------------------------------*/
3798 void BuildFlow(pBlock *pb)
3801 pCode *last_pci=NULL;
3808 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3809 /* Insert a pCodeFlow object at the beginning of a pBlock */
3811 InsertpFlow(pb->pcHead, &pflow);
3813 //pflow = newpCodeFlow(); /* Create a new Flow object */
3814 //pflow->next = pb->pcHead; /* Make the current head the next object */
3815 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3816 //pb->pcHead = pflow; /* Make the Flow object the head */
3819 for( pc = findNextInstruction(pb->pcHead);
3821 pc=findNextInstruction(pc)) {
3824 PCI(pc)->pcflow = PCFL(pflow);
3826 //fprintf(stderr," build: ");
3827 //pflow->print(stderr,pflow);
3829 if( PCI(pc)->isSkip) {
3831 /* The two instructions immediately following this one
3832 * mark the beginning of a new flow segment */
3834 while(pc && PCI(pc)->isSkip) {
3836 PCI(pc)->pcflow = PCFL(pflow);
3840 InsertpFlow(pc, &pflow);
3841 pc=findNextInstruction(pc->next);
3849 PCI(pc)->pcflow = PCFL(pflow);
3851 InsertpFlow(pc, &pflow);
3853 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3855 InsertpFlow(pc, &pflow);
3858 } else if (checkLabel(pc)) {
3860 /* This instruction marks the beginning of a
3861 * new flow segment */
3866 /* If the previous pCode is not a flow object, then
3867 * insert a new flow object. (This check prevents
3868 * two consecutive flow objects from being insert in
3869 * the case where a skip instruction preceeds an
3870 * instruction containing a label.) */
3872 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3873 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3875 PCI(pc)->pcflow = PCFL(pflow);
3882 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3884 PCFL(pflow)->end = pb->pcTail;
3887 /*-------------------------------------------------------------------*/
3888 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3889 /* the flow blocks. */
3891 * unBuildFlow removes pCodeFlow objects from a pCode chain
3893 /*-----------------------------------------------------------------*/
3894 void unBuildFlow(pBlock *pb)
3909 if(PCI(pc)->pcflow) {
3910 //free(PCI(pc)->pcflow);
3911 PCI(pc)->pcflow = NULL;
3914 } else if(isPCFL(pc) )
3923 /*-----------------------------------------------------------------*/
3924 /*-----------------------------------------------------------------*/
3925 void dumpCond(int cond)
3928 static char *pcc_str[] = {
3942 int ncond = sizeof(pcc_str) / sizeof(char *);
3945 fprintf(stderr, "0x%04X\n",cond);
3947 for(i=0,j=1; i<ncond; i++, j<<=1)
3949 fprintf(stderr, " %s\n",pcc_str[i]);
3953 /*-----------------------------------------------------------------*/
3954 /*-----------------------------------------------------------------*/
3955 void FlowStats(pCodeFlow *pcflow)
3963 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3965 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3968 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3973 fprintf(stderr, " FlowStats inCond: ");
3974 dumpCond(pcflow->inCond);
3975 fprintf(stderr, " FlowStats outCond: ");
3976 dumpCond(pcflow->outCond);
3980 /*-----------------------------------------------------------------*
3981 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3982 * if it affects the banking bits.
3984 * return: -1 == Banking bits are unaffected by this pCode.
3986 * return: > 0 == Banking bits are affected.
3988 * If the banking bits are affected, then the returned value describes
3989 * which bits are affected and how they're affected. The lower half
3990 * of the integer maps to the bits that are affected, the upper half
3991 * to whether they're set or cleared.
3993 *-----------------------------------------------------------------*/
3995 #define SET_BANK_BIT (1 << 16)
3996 #define CLR_BANK_BIT 0
3998 static int isBankInstruction(pCode *pc)
4006 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4008 // Check to see if the register banks are changing
4009 if(PCI(pc)->isModReg) {
4011 pCodeOp *pcop = PCI(pc)->pcop;
4012 switch(PCI(pc)->op) {
4015 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4016 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4017 return SET_BANK_BIT | PIC_RP0_BIT;
4020 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4021 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4022 return CLR_BANK_BIT | PIC_RP0_BIT;
4027 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4028 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4029 return CLR_BANK_BIT | PIC_RP1_BIT;
4031 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4032 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4033 return CLR_BANK_BIT | PIC_RP1_BIT;
4037 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4038 //genericPrint(stderr, pc);
4049 /*-----------------------------------------------------------------*/
4050 /*-----------------------------------------------------------------*/
4052 static void FillFlow(pCodeFlow *pcflow)
4060 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4062 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4065 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4072 isBankInstruction(pc);
4074 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4077 fprintf(stderr, " FillFlow - Bad end of flow\n");
4079 fprintf(stderr, " FillFlow - Ending flow with\n ");
4080 pc->print(stderr,pc);
4083 fprintf(stderr, " FillFlow inCond: ");
4084 dumpCond(pcflow->inCond);
4085 fprintf(stderr, " FillFlow outCond: ");
4086 dumpCond(pcflow->outCond);
4091 /*-----------------------------------------------------------------*/
4092 /*-----------------------------------------------------------------*/
4093 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4095 pCodeFlowLink *fromLink, *toLink;
4097 if(!from || !to || !to->pcflow || !from->pcflow)
4100 fromLink = newpCodeFlowLink(from->pcflow);
4101 toLink = newpCodeFlowLink(to->pcflow);
4103 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4104 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4108 /*-----------------------------------------------------------------*
4109 * void LinkFlow(pBlock *pb)
4111 * In BuildFlow, the PIC code has been partitioned into contiguous
4112 * non-branching segments. In LinkFlow, we determine the execution
4113 * order of these segments. For example, if one of the segments ends
4114 * with a skip, then we know that there are two possible flow segments
4115 * to which control may be passed.
4116 *-----------------------------------------------------------------*/
4117 void LinkFlow(pBlock *pb)
4123 //fprintf(stderr,"linkflow \n");
4125 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4127 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4130 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4132 //fprintf(stderr," link: ");
4133 //pcflow->print(stderr,pcflow);
4135 //FillFlow(PCFL(pcflow));
4137 pc = PCFL(pcflow)->end;
4139 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4140 if(isPCI_SKIP(pc)) {
4141 //fprintf(stderr, "ends with skip\n");
4142 //pc->print(stderr,pc);
4143 pct=findNextInstruction(pc->next);
4144 LinkFlow_pCode(PCI(pc),PCI(pct));
4145 pct=findNextInstruction(pct->next);
4146 LinkFlow_pCode(PCI(pc),PCI(pct));
4150 if(isPCI_BRANCH(pc)) {
4151 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4153 //fprintf(stderr, "ends with branch\n ");
4154 //pc->print(stderr,pc);
4156 if(!(pcol && isPCOLAB(pcol))) {
4157 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4158 pc->print(stderr,pc);
4159 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4164 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4165 LinkFlow_pCode(PCI(pc),PCI(pct));
4167 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4168 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4169 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4175 //fprintf(stderr, "ends with non-branching instruction:\n");
4176 //pc->print(stderr,pc);
4178 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4184 //fprintf(stderr, "ends with unknown\n");
4185 //pc->print(stderr,pc);
4189 //fprintf(stderr, "ends with nothing: ERROR\n");
4193 /*-----------------------------------------------------------------*/
4194 /*-----------------------------------------------------------------*/
4196 /*-----------------------------------------------------------------*/
4197 /*-----------------------------------------------------------------*/
4198 int isPCinFlow(pCode *pc, pCode *pcflow)
4204 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4207 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4213 /*-----------------------------------------------------------------*/
4214 /*-----------------------------------------------------------------*/
4216 static void BanksUsedFlow2(pCode *pcflow)
4225 if(!isPCFL(pcflow)) {
4226 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4230 pc = findNextInstruction(pcflow->next);
4232 PCFL(pcflow)->lastBank = -1;
4234 while(isPCinFlow(pc,pcflow)) {
4236 int bank_selected = isBankInstruction(pc);
4238 //if(PCI(pc)->pcflow)
4239 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4241 if(bank_selected > 0) {
4242 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4244 // This instruction is modifying banking bits before accessing registers
4246 PCFL(pcflow)->firstBank = -1;
4248 if(PCFL(pcflow)->lastBank == -1)
4249 PCFL(pcflow)->lastBank = 0;
4251 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4252 if(bank_selected & SET_BANK_BIT)
4253 PCFL(pcflow)->lastBank |= bank;
4257 reg = getRegFromInstruction(pc);
4259 if(reg && !isREGinBank(reg, bank)) {
4260 int allbanks = REGallBanks(reg);
4262 PCFL(pcflow)->firstBank = allbanks;
4264 PCFL(pcflow)->lastBank = allbanks;
4271 pc = findNextInstruction(pc->next);
4274 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4275 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4278 /*-----------------------------------------------------------------*/
4279 /*-----------------------------------------------------------------*/
4281 static void BanksUsedFlow(pBlock *pb)
4286 //pb->pcHead->print(stderr, pb->pcHead);
4288 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4289 //pcflow->print(stderr,pcflow);
4291 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4293 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4295 BanksUsedFlow2(pcflow);
4301 /*-----------------------------------------------------------------*/
4302 /*-----------------------------------------------------------------*/
4303 static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci)
4306 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4308 /* Move the label, if there is one */
4311 new_pci->label = pci->label;
4315 /* Move the C code comment, if there is one */
4318 new_pci->cline = pci->cline;
4322 /* The new instruction has the same pcflow block */
4323 new_pci->pcflow = pci->pcflow;
4327 /*-----------------------------------------------------------------*/
4328 /*-----------------------------------------------------------------*/
4329 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4333 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4335 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4338 /*-----------------------------------------------------------------*/
4339 /*-----------------------------------------------------------------*/
4340 static void insertBankSel(pCodeInstruction *pci, const char *name)
4344 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4345 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4346 if (pcop->name == 0)
4347 pcop->name = strdup(name);
4348 new_pc = newpCode(POC_BANKSEL, pcop);
4350 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4353 /*-----------------------------------------------------------------*/
4354 /* If the register is a fixed known addess then we can assign the */
4355 /* bank selection bits. Otherwise the linker is going to assign */
4356 /* the register location and thus has to set bank selection bits */
4357 /* through the banksel directive. */
4358 /* One critical assumption here is that within this C module all */
4359 /* the locally allocated registers are in the same udata sector. */
4360 /* Therefore banksel is only called for external registers or the */
4361 /* first time a local register is encountered. */
4362 /*-----------------------------------------------------------------*/
4363 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4364 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4367 int a = reg->alias>>7;
4369 return cur_bank; // This register is available in all banks
4370 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4371 return cur_bank; // This register is available in banks 0 & 1
4373 if (reg->address&0x80) {
4374 if ((cur_bank==1)||(cur_bank==3)) {
4375 return cur_bank; // This register is available in banks 1 & 3
4378 if ((cur_bank==0)||(cur_bank==1)) {
4379 return cur_bank; // This register is available in banks 0 & 2
4384 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4386 LastRegIdx = reg->rIdx;
4389 bank = REG_BANK(reg);
4390 } else if (reg->isExtern) {
4391 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4393 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4395 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.
4396 return 'L'; // Local registers are presumed to be in same linker assigned bank
4397 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4398 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4399 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4400 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4401 } 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
4402 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4403 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4404 } else { // Current bank and new register banks known - can set bank bits
4405 switch((cur_bank^bank) & 3) {
4409 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4412 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4415 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4416 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4424 /*-----------------------------------------------------------------*/
4425 /* Check for bank selection pcodes instructions and modify */
4426 /* cur_bank to match. */
4427 /*-----------------------------------------------------------------*/
4428 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4430 if (isSTATUS_REG(reg)) {
4432 if (PCI(pc)->op == POC_BCF) {
4433 int old_bank = *cur_bank;
4434 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4435 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4436 if (*cur_bank & ~(0x3))
4439 *cur_bank = *cur_bank&0x2;
4440 LastRegIdx = reg->rIdx;
4441 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4442 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4443 if (*cur_bank & ~(0x3))
4446 *cur_bank = *cur_bank&0x1;
4447 LastRegIdx = reg->rIdx;
4449 return old_bank != *cur_bank;
4452 if (PCI(pc)->op == POC_BSF) {
4453 int old_bank = *cur_bank;
4454 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4455 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4456 if (*cur_bank & ~(0x3))
4459 *cur_bank = (*cur_bank&0x2) | 0x1;
4460 LastRegIdx = reg->rIdx;
4461 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4462 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4463 if (*cur_bank & ~(0x3))
4466 *cur_bank = (*cur_bank&0x1) | 0x2;
4467 LastRegIdx = reg->rIdx;
4469 return old_bank != *cur_bank;
4472 } else if (PCI(pc)->op == POC_BANKSEL) {
4473 int old_bank = *cur_bank;
4474 *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L';
4475 LastRegIdx = reg->rIdx;
4476 return old_bank != *cur_bank;
4482 /*-----------------------------------------------------------------*/
4483 /* Set bank selection if necessary */
4484 /*-----------------------------------------------------------------*/
4485 static int DoBankSelect(pCode *pc, int cur_bank) {
4493 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4494 if (pcf && isPCF(pcf)) {
4496 int rbank = 'U'; // Undetermined
4497 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4498 // Check all the returns to work out what bank is selected
4499 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4501 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4503 rbank = PCFL(pcfr)->lastBank;
4505 if (rbank != PCFL(pcfr)->lastBank)
4506 return -1; // Unknown bank - multiple returns with different banks
4511 return -1; // Unknown bank
4513 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4514 /* Extern functions may use registers in different bank - must call banksel */
4515 return -1; /* Unknown bank */
4519 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4520 return -1; /* New bank unknown - linkers choice. */
4523 reg = getRegFromInstruction(pc);
4526 if (IsBankChange(pc,reg,&cur_bank))
4529 if (!isPCI_LIT(pc)) {
4531 /* Examine the instruction before this one to make sure it is
4532 * not a skip type instruction */
4533 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4535 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4536 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4538 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4540 if (!PCI(pc)->pcflow)
4541 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4543 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4549 /*-----------------------------------------------------------------*/
4550 /*-----------------------------------------------------------------*/
4552 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4560 pc = findNextInstruction(pcfl->pc.next);
4562 while(isPCinFlow(pc,PCODE(pcfl))) {
4564 cur_bank = DoBankSelect(pc,cur_bank);
4566 pc = findNextInstruction(pc->next);
4570 if(pcprev && cur_bank) {
4571 // Set bank state to unknown at the end of each flow block
4577 /*-----------------------------------------------------------------*/
4578 /*int compareBankFlow - compare the banking requirements between */
4580 /*-----------------------------------------------------------------*/
4582 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4585 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4588 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4591 if(pcflow->firstBank == -1)
4595 if(pcflowLink->pcflow->firstBank == -1) {
4596 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4597 pcflowLink->pcflow->to :
4598 pcflowLink->pcflow->from);
4599 return compareBankFlow(pcflow, pctl, toORfrom);
4603 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4606 pcflowLink->bank_conflict++;
4607 pcflowLink->pcflow->FromConflicts++;
4608 pcflow->ToConflicts++;
4611 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4614 pcflowLink->bank_conflict++;
4615 pcflowLink->pcflow->ToConflicts++;
4616 pcflow->FromConflicts++;
4620 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4621 pcflowLink->pcflow->pc.seq,
4622 pcflowLink->pcflow->FromConflicts,
4623 pcflowLink->pcflow->ToConflicts);
4629 /*-----------------------------------------------------------------*/
4630 /*-----------------------------------------------------------------*/
4632 void FixBankFlow(pBlock *pb)
4636 pCodeFlowLink *pcfl;
4638 pCode *pcflow_max_To=NULL;
4639 pCode *pcflow_max_From=NULL;
4640 int max_ToConflicts=0;
4641 int max_FromConflicts=0;
4643 //fprintf(stderr,"Fix Bank flow \n");
4644 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4648 First loop through all of the flow objects in this pcode block
4649 and fix the ones that have banking conflicts between the
4653 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4655 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4657 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4659 if(!isPCFL(pcflow)) {
4660 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4664 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4665 PCFL(pcflow)->firstBank >= 0 &&
4666 PCFL(pcflow)->lastBank >= 0 ) {
4668 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4669 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4671 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4672 BanksUsedFlow2(pcflow);
4677 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4679 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4681 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4686 if(!isPCFL(pcflow)) {
4687 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4691 PCFL(pcflow)->FromConflicts = 0;
4692 PCFL(pcflow)->ToConflicts = 0;
4697 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4698 pcfl = setFirstItem(PCFL(pcflow)->from);
4701 pc = PCODE(pcfl->pcflow);
4704 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4705 pc->print(stderr,pc);
4708 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4711 pcfl=setNextItem(PCFL(pcflow)->from);
4714 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4715 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4717 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4718 BanksUsedFlow2(pcflow);
4720 continue; / * Don't need to check the flow from here - it's already been fixed * /
4727 pcfl = setFirstItem(PCFL(pcflow)->to);
4730 pc = PCODE(pcfl->pcflow);
4732 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4733 pc->print(stderr,pc);
4736 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4739 pcfl=setNextItem(PCFL(pcflow)->to);
4742 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4743 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4745 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4746 BanksUsedFlow2(pcflow);
4751 Loop through the flow objects again and find the ones with the
4755 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4757 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4759 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4760 pcflow_max_To = pcflow;
4762 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4763 pcflow_max_From = pcflow;
4767 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4768 PCFL(pcflow_max_To)->pc.seq,
4769 PCFL(pcflow_max_To)->ToConflicts);
4772 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4773 PCFL(pcflow_max_From)->pc.seq,
4774 PCFL(pcflow_max_From)->FromConflicts);
4779 /*-----------------------------------------------------------------*/
4780 /*-----------------------------------------------------------------*/
4781 void DumpFlow(pBlock *pb)
4785 pCodeFlowLink *pcfl;
4788 fprintf(stderr,"Dump flow \n");
4789 pb->pcHead->print(stderr, pb->pcHead);
4791 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4792 pcflow->print(stderr,pcflow);
4794 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4796 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4798 if(!isPCFL(pcflow)) {
4799 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4802 fprintf(stderr,"dumping: ");
4803 pcflow->print(stderr,pcflow);
4804 FlowStats(PCFL(pcflow));
4806 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4808 pc = PCODE(pcfl->pcflow);
4810 fprintf(stderr, " from seq %d:\n",pc->seq);
4812 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4813 pc->print(stderr,pc);
4818 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4820 pc = PCODE(pcfl->pcflow);
4822 fprintf(stderr, " to seq %d:\n",pc->seq);
4824 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4825 pc->print(stderr,pc);
4834 /*-----------------------------------------------------------------*/
4835 /*-----------------------------------------------------------------*/
4836 int OptimizepBlock(pBlock *pb)
4841 if(!pb || !peepOptimizing)
4844 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4846 for(pc = pb->pcHead; pc; pc = pc->next)
4847 matches += pCodePeepMatchRule(pc);
4850 pc = findNextInstruction(pb->pcHead);
4858 if(pCodePeepMatchRule(pc)) {
4863 pc = findNextInstruction(pcprev->next);
4865 pc = findNextInstruction(pb->pcHead);
4867 pc = findNextInstruction(pc->next);
4871 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4876 /*-----------------------------------------------------------------*/
4877 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4878 /*-----------------------------------------------------------------*/
4879 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4883 for(pc = pcs; pc; pc = pc->next) {
4885 if((pc->type == PC_OPCODE) &&
4887 (PCI(pc)->pcop->type == PO_LABEL) &&
4888 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4896 /*-----------------------------------------------------------------*/
4897 /*-----------------------------------------------------------------*/
4898 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4905 (PCI(pc)->pcop->type == PO_LABEL)) {
4907 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4909 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4911 free(pcol->pcop.name);
4913 /* If the key is negative, then we (probably) have a label to
4914 * a function and the name is already defined */
4917 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4921 //sprintf(buffer,"_%05d_DS_",pcl->key);
4923 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4925 pcol->pcop.name = Safe_strdup(s);
4926 pcol->key = pcl->key;
4927 //pc->print(stderr,pc);
4934 /*-----------------------------------------------------------------*/
4935 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4936 /* pCode chain if they're not used. */
4937 /*-----------------------------------------------------------------*/
4938 void pBlockRemoveUnusedLabels(pBlock *pb)
4940 pCode *pc; pCodeLabel *pcl;
4945 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4947 pBranch *pbr = PCI(pc)->label;
4948 if(pbr && pbr->next) {
4949 pCode *pcd = pb->pcHead;
4951 //fprintf(stderr, "multiple labels\n");
4952 //pc->print(stderr,pc);
4957 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4958 //fprintf(stderr,"Used by:\n");
4959 //pcd->print(stderr,pcd);
4961 exchangeLabels(PCL(pbr->pc),pcd);
4970 for(pc = pb->pcHead; pc; pc = pc->next) {
4972 if(isPCL(pc)) // Label pcode
4974 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4975 pcl = PCL(PCI(pc)->label->pc);
4978 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4980 /* This pCode is a label, so search the pBlock to see if anyone
4983 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4984 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4985 /* Couldn't find an instruction that refers to this label
4986 * So, unlink the pCode label from it's pCode chain
4987 * and destroy the label */
4988 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4990 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4991 if(pc->type == PC_LABEL) {
4993 pCodeLabelDestruct(pc);
4995 unlinkpCodeFromBranch(pc, PCODE(pcl));
4996 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5007 /*-----------------------------------------------------------------*/
5008 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5009 /* chain and put them into pBranches that are */
5010 /* associated with the appropriate pCode */
5012 /*-----------------------------------------------------------------*/
5013 void pBlockMergeLabels(pBlock *pb)
5016 pCode *pc, *pcnext=NULL;
5021 /* First, Try to remove any unused labels */
5022 //pBlockRemoveUnusedLabels(pb);
5024 /* Now loop through the pBlock and merge the labels with the opcodes */
5027 // for(pc = pb->pcHead; pc; pc = pc->next) {
5030 pCode *pcn = pc->next;
5032 if(pc->type == PC_LABEL) {
5034 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5035 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5036 if((pcnext = findNextInstruction(pc) )) {
5038 // Unlink the pCode label from it's pCode chain
5041 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5042 // And link it into the instruction's pBranch labels. (Note, since
5043 // it's possible to have multiple labels associated with one instruction
5044 // we must provide a means to accomodate the additional labels. Thus
5045 // the labels are placed into the singly-linked list "label" as
5046 // opposed to being a single member of the pCodeInstruction.)
5048 //_ALLOC(pbr,sizeof(pBranch));
5049 pbr = Safe_calloc(1,sizeof(pBranch));
5053 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5056 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5058 } else if(pc->type == PC_CSOURCE) {
5060 /* merge the source line symbolic info into the next instruction */
5061 if((pcnext = findNextInstruction(pc) )) {
5063 // Unlink the pCode label from it's pCode chain
5065 PCI(pcnext)->cline = PCCS(pc);
5066 //fprintf(stderr, "merging CSRC\n");
5067 //genericPrint(stderr,pcnext);
5073 pBlockRemoveUnusedLabels(pb);
5077 /*-----------------------------------------------------------------*/
5078 /*-----------------------------------------------------------------*/
5079 int OptimizepCode(char dbName)
5081 #define MAX_PASSES 4
5090 DFPRINTF((stderr," Optimizing pCode\n"));
5094 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5095 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5096 matches += OptimizepBlock(pb);
5099 while(matches && ++passes < MAX_PASSES);
5104 /*-----------------------------------------------------------------*/
5105 /* popCopyGPR2Bit - copy a pcode operator */
5106 /*-----------------------------------------------------------------*/
5108 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5112 pcop = newpCodeOpBit(pc->name, bitval, 0);
5114 if( !( (pcop->type == PO_LABEL) ||
5115 (pcop->type == PO_LITERAL) ||
5116 (pcop->type == PO_STR) ))
5117 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5123 /*-----------------------------------------------------------------*/
5124 /*-----------------------------------------------------------------*/
5125 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5128 int firstBank = 'U';
5133 for (pc=pb->pcHead; pc; pc=pc->next) {
5135 firstBank = PCFL(pc)->firstBank;
5139 if (firstBank != 'U') {
5140 /* This block has already been done */
5141 if (firstBank != cur_bank) {
5142 /* This block has started with a different bank - must adjust it */
5143 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5146 regs *reg = getRegFromInstruction(pc);
5148 DoBankSelect(pc,cur_bank);
5158 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5161 for (pc=pb->pcHead; pc; pc=pc->next) {
5163 PCFL(pc)->firstBank = cur_bank;
5166 cur_bank = DoBankSelect(pc,cur_bank);
5169 /* Trace through branches and set the bank selection as required. */
5172 for (pc=pb->pcHead; pc; pc=pc->next) {
5174 PCFL(pc)->firstBank = cur_bank;
5178 if (PCI(pc)->op == POC_GOTO) {
5179 int lastRegIdx = LastRegIdx;
5181 /* Trace through branch */
5182 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5185 regs *reg = getRegFromInstruction(pcl);
5187 int bankUnknown = -1;
5188 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5190 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5196 LastRegIdx = lastRegIdx;
5198 /* Keep track out current bank */
5199 regs *reg = getRegFromInstruction(pc);
5201 IsBankChange(pc,reg,&cur_bank);
5208 /*-----------------------------------------------------------------*/
5209 /*-----------------------------------------------------------------*/
5210 void pBlockDestruct(pBlock *pb)
5221 /*-----------------------------------------------------------------*/
5222 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5223 /* name dbName and combine them */
5224 /* into one block */
5225 /*-----------------------------------------------------------------*/
5226 void mergepBlocks(char dbName)
5229 pBlock *pb, *pbmerged = NULL,*pbn;
5231 pb = the_pFile->pbHead;
5233 //fprintf(stderr," merging blocks named %c\n",dbName);
5237 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5238 if( getpBlock_dbName(pb) == dbName) {
5240 //fprintf(stderr," merged block %c\n",dbName);
5245 addpCode2pBlock(pbmerged, pb->pcHead);
5246 /* addpCode2pBlock doesn't handle the tail: */
5247 pbmerged->pcTail = pb->pcTail;
5249 pb->prev->next = pbn;
5251 pbn->prev = pb->prev;
5256 //printpBlock(stderr, pbmerged);
5263 /*-----------------------------------------------------------------*/
5264 /* AnalyzeFlow - Examine the flow of the code and optimize */
5266 /* level 0 == minimal optimization */
5267 /* optimize registers that are used only by two instructions */
5268 /* level 1 == maximal optimization */
5269 /* optimize by looking at pairs of instructions that use the */
5271 /*-----------------------------------------------------------------*/
5273 void AnalyzeFlow(int level)
5275 static int times_called=0;
5283 /* if this is not the first time this function has been called,
5284 then clean up old flow information */
5285 if(times_called++) {
5286 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5289 RegsUnMapLiveRanges();
5295 /* Phase 2 - Flow Analysis - Register Banking
5297 * In this phase, the individual flow blocks are examined
5298 * and register banking is fixed.
5301 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5302 //FixRegisterBanking(pb);
5304 /* Phase 2 - Flow Analysis
5306 * In this phase, the pCode is partition into pCodeFlow
5307 * blocks. The flow blocks mark the points where a continuous
5308 * stream of instructions changes flow (e.g. because of
5309 * a call or goto or whatever).
5312 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5316 /* Phase 2 - Flow Analysis - linking flow blocks
5318 * In this phase, the individual flow blocks are examined
5319 * to determine their order of excution.
5322 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5325 /* Phase 3 - Flow Analysis - Flow Tree
5327 * In this phase, the individual flow blocks are examined
5328 * to determine their order of excution.
5331 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5335 /* Phase x - Flow Analysis - Used Banks
5337 * In this phase, the individual flow blocks are examined
5338 * to determine the Register Banks they use
5341 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5345 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5346 pCodeRegMapLiveRanges(pb);
5348 RemoveUnusedRegisters();
5350 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5351 pCodeRegOptimizeRegUsage(level);
5357 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5362 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5364 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5365 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5366 pcflow = pcflow->next) {
5368 FillFlow(PCFL(pcflow));
5373 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5375 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5376 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5377 pcflow = pcflow->next) {
5379 FlowStats(PCFL(pcflow));
5385 /*-----------------------------------------------------------------*/
5386 /* AnalyzeBanking - Called after the memory addresses have been */
5387 /* assigned to the registers. */
5389 /*-----------------------------------------------------------------*/
5391 void AnalyzeBanking(void)
5395 if(!picIsInitialized()) {
5396 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5397 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5398 fprintf(stderr,"support/scripts/inc2h.pl\n");
5399 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5404 /* Phase x - Flow Analysis - Used Banks
5406 * In this phase, the individual flow blocks are examined
5407 * to determine the Register Banks they use
5413 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5414 // BanksUsedFlow(pb);
5415 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5416 FixRegisterBanking(pb,-1); // cur_bank is unknown
5420 /*-----------------------------------------------------------------*/
5421 /*-----------------------------------------------------------------*/
5422 DEFSETFUNC (resetrIdx)
5424 if (!((regs *)item)->isFixed)
5425 ((regs *)item)->rIdx = 0;
5430 /*-----------------------------------------------------------------*/
5431 /* InitRegReuse - Initialises variables for code analyzer */
5432 /*-----------------------------------------------------------------*/
5434 void InitReuseReg(void)
5436 /* Find end of statically allocated variables for start idx */
5437 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5439 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5440 if (r->type != REG_SFR) {
5441 maxIdx += r->size; /* Increment for all statically allocated variables */
5445 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5448 /*-----------------------------------------------------------------*/
5449 /*-----------------------------------------------------------------*/
5450 static unsigned register_reassign(pBlock *pb, unsigned idx)
5454 /* check recursion */
5455 pc = setFirstItem(pb->function_entries);
5461 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5463 if (pb->tregisters) {
5465 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5466 if (r->type == REG_GPR) {
5468 if (r->rIdx < (int)idx) {
5471 if (peakIdx < idx) peakIdx = idx;
5472 sprintf(s,"r0x%02X", r->rIdx);
5473 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5475 r->name = Safe_strdup(s);
5481 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5483 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5484 char *dest = get_op_from_instruction(PCI(pc));
5486 pCode *pcn = findFunction(dest);
5488 register_reassign(pcn->pb,idx);
5497 /*------------------------------------------------------------------*/
5498 /* ReuseReg were call tree permits */
5500 /* Re-allocate the GPR for optimum reuse for a given pblock */
5501 /* eg if a function m() calls function f1() and f2(), where f1 */
5502 /* allocates a local variable vf1 and f2 allocates a local */
5503 /* variable vf2. Then providing f1 and f2 do not call each other */
5504 /* they may share the same general purpose registers for vf1 and */
5506 /* This is done by first setting the the regs rIdx to start after */
5507 /* all the global variables, then walking through the call tree */
5508 /* renaming the registers to match their new idx and incrementng */
5509 /* it as it goes. If a function has already been called it will */
5510 /* only rename the registers if it has already used up those */
5511 /* registers ie rIdx of the function's registers is lower than the */
5512 /* current rIdx. That way the register will not be reused while */
5513 /* still being used by an eariler function call. */
5515 /* Note for this to work the fucntions need to be declared static. */
5517 /*------------------------------------------------------------------*/
5522 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5523 /* Non static functions can be called from other modules so their registers must reassign */
5524 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5525 register_reassign(pb,peakIdx);
5529 /*-----------------------------------------------------------------*/
5530 /* buildCallTree - look at the flow and extract all of the calls */
5532 /*-----------------------------------------------------------------*/
5534 void buildCallTree(void )
5543 /* Now build the call tree.
5544 First we examine all of the pCodes for functions.
5545 Keep in mind that the function boundaries coincide
5546 with pBlock boundaries.
5548 The algorithm goes something like this:
5549 We have two nested loops. The outer loop iterates
5550 through all of the pBlocks/functions. The inner
5551 loop iterates through all of the pCodes for
5552 a given pBlock. When we begin iterating through
5553 a pBlock, the variable pc_fstart, pCode of the start
5554 of a function, is cleared. We then search for pCodes
5555 of type PC_FUNCTION. When one is encountered, we
5556 initialize pc_fstart to this and at the same time
5557 associate a new pBranch object that signifies a
5558 branch entry. If a return is found, then this signifies
5559 a function exit point. We'll link the pCodes of these
5560 returns to the matching pc_fstart.
5562 When we're done, a doubly linked list of pBranches
5563 will exist. The head of this list is stored in
5564 `the_pFile', which is the meta structure for all
5565 of the pCode. Look at the printCallTree function
5566 on how the pBranches are linked together.
5569 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5570 pCode *pc_fstart=NULL;
5571 for(pc = pb->pcHead; pc; pc = pc->next) {
5573 pCodeFunction *pcf = PCF(pc);
5576 if(STRCASECMP(pcf->fname, "_main") == 0) {
5577 //fprintf(stderr," found main \n");
5578 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5582 pbr = Safe_calloc(1,sizeof(pBranch));
5583 pbr->pc = pc_fstart = pc;
5586 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5588 // Here's a better way of doing the same:
5589 addSet(&pb->function_entries, pc);
5592 // Found an exit point in a function, e.g. return
5593 // (Note, there may be more than one return per function)
5595 pBranchLink(PCF(pc_fstart), pcf);
5597 addSet(&pb->function_exits, pc);
5599 } else if(isCALL(pc)) {
5600 addSet(&pb->function_calls,pc);
5606 /*-----------------------------------------------------------------*/
5607 /* AnalyzepCode - parse the pCode that has been generated and form */
5608 /* all of the logical connections. */
5610 /* Essentially what's done here is that the pCode flow is */
5612 /*-----------------------------------------------------------------*/
5614 void AnalyzepCode(char dbName)
5625 /* Phase 1 - Register allocation and peep hole optimization
5627 * The first part of the analysis is to determine the registers
5628 * that are used in the pCode. Once that is done, the peep rules
5629 * are applied to the code. We continue to loop until no more
5630 * peep rule optimizations are found (or until we exceed the
5631 * MAX_PASSES threshold).
5633 * When done, the required registers will be determined.
5639 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5641 /* First, merge the labels with the instructions */
5642 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5643 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5645 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5646 pBlockMergeLabels(pb);
5649 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5653 changes = OptimizepCode(dbName);
5655 } while(changes && (i++ < MAX_PASSES));
5660 /*-----------------------------------------------------------------*/
5661 /* ispCodeFunction - returns true if *pc is the pCode of a */
5663 /*-----------------------------------------------------------------*/
5664 bool ispCodeFunction(pCode *pc)
5667 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5673 /*-----------------------------------------------------------------*/
5674 /* findFunction - Search for a function by name (given the name) */
5675 /* in the set of all functions that are in a pBlock */
5676 /* (note - I expect this to change because I'm planning to limit */
5677 /* pBlock's to just one function declaration */
5678 /*-----------------------------------------------------------------*/
5679 pCode *findFunction(char *fname)
5686 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5688 pc = setFirstItem(pb->function_entries);
5691 if((pc->type == PC_FUNCTION) &&
5693 (strcmp(fname, PCF(pc)->fname)==0))
5696 pc = setNextItem(pb->function_entries);
5704 void MarkUsedRegisters(set *regset)
5709 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5710 r2 = pic14_regWithIdx(r1->rIdx);
5718 void pBlockStats(FILE *of, pBlock *pb)
5724 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5726 // for now just print the first element of each set
5727 pc = setFirstItem(pb->function_entries);
5729 fprintf(of,";entry: ");
5732 pc = setFirstItem(pb->function_exits);
5734 fprintf(of,";has an exit\n");
5738 pc = setFirstItem(pb->function_calls);
5740 fprintf(of,";functions called:\n");
5743 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5744 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5746 pc = setNextItem(pb->function_calls);
5750 r = setFirstItem(pb->tregisters);
5752 int n = elementsInSet(pb->tregisters);
5754 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5757 fprintf(of,"; %s\n",r->name);
5758 r = setNextItem(pb->tregisters);
5763 /*-----------------------------------------------------------------*/
5764 /*-----------------------------------------------------------------*/
5766 static void sequencepCode(void)
5772 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5774 pb->seq = GpCodeSequenceNumber+1;
5776 for( pc = pb->pcHead; pc; pc = pc->next)
5777 pc->seq = ++GpCodeSequenceNumber;
5783 /*-----------------------------------------------------------------*/
5784 /*-----------------------------------------------------------------*/
5786 set *register_usage(pBlock *pb)
5789 set *registers=NULL;
5790 set *registersInCallPath = NULL;
5792 / * check recursion * /
5794 pc = setFirstItem(pb->function_entries);
5801 if(pc->type != PC_FUNCTION)
5802 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5804 pc = setFirstItem(pb->function_calls);
5805 for( ; pc; pc = setNextItem(pb->function_calls)) {
5807 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5808 char *dest = get_op_from_instruction(PCI(pc));
5810 pcn = findFunction(dest);
5812 registersInCallPath = register_usage(pcn->pb);
5814 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5819 pBlockStats(stderr,pb); // debug
5822 // Mark the registers in this block as used.
5824 MarkUsedRegisters(pb->tregisters);
5825 if(registersInCallPath) {
5826 / * registers were used in the functions this pBlock has called * /
5827 / * so now, we need to see if these collide with the ones we are * /
5830 regs *r1,*r2, *newreg;
5832 DFPRINTF((stderr,"comparing registers\n"));
5834 r1 = setFirstItem(registersInCallPath);
5836 if (r1->type != REG_STK) {
5837 r2 = setFirstItem(pb->tregisters);
5839 while(r2 && (r2->type != REG_STK)) {
5841 if(r2->rIdx == r1->rIdx) {
5842 newreg = pic14_findFreeReg(REG_GPR);
5846 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5850 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5851 r1->rIdx, newreg->rIdx));
5852 r2->rIdx = newreg->rIdx;
5854 r2->name = Safe_strdup(newreg->name);
5858 newreg->wasUsed = 1;
5860 r2 = setNextItem(pb->tregisters);
5864 r1 = setNextItem(registersInCallPath);
5867 / * Collisions have been resolved. Now free the registers in the call path * /
5868 r1 = setFirstItem(registersInCallPath);
5870 newreg = pic14_regWithIdx(r1->rIdx);
5871 if (newreg) newreg->isFree = 1;
5872 r1 = setNextItem(registersInCallPath);
5876 // MarkUsedRegisters(pb->registers);
5878 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5881 DFPRINTF((stderr,"returning regs\n"));
5883 DFPRINTF((stderr,"not returning regs\n"));
5885 DFPRINTF((stderr,"pBlock after register optim.\n"));
5886 pBlockStats(stderr,pb); // debug
5893 /*-----------------------------------------------------------------*/
5894 /* printCallTree - writes the call tree to a file */
5896 /*-----------------------------------------------------------------*/
5897 void pct2(FILE *of,pBlock *pb,int indent)
5901 // set *registersInCallPath = NULL;
5907 return; //recursion ?
5909 pc = setFirstItem(pb->function_entries);
5916 for(i=0;i<indent;i++) // Indentation
5919 if(pc->type == PC_FUNCTION)
5920 fprintf(of,"%s\n",PCF(pc)->fname);
5925 pc = setFirstItem(pb->function_calls);
5926 for( ; pc; pc = setNextItem(pb->function_calls)) {
5928 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5929 char *dest = get_op_from_instruction(PCI(pc));
5931 pcn = findFunction(dest);
5933 pct2(of,pcn->pb,indent+1);
5935 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5943 /*-----------------------------------------------------------------*/
5944 /* printCallTree - writes the call tree to a file */
5946 /*-----------------------------------------------------------------*/
5948 void printCallTree(FILE *of)
5960 fprintf(of, "\npBlock statistics\n");
5961 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5966 fprintf(of,"Call Tree\n");
5967 pbr = the_pFile->functions;
5971 if(!ispCodeFunction(pc))
5972 fprintf(of,"bug in call tree");
5975 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5977 while(pc->next && !ispCodeFunction(pc->next)) {
5979 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5980 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5988 fprintf(of,"\n**************\n\na better call tree\n");
5989 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5994 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5995 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6001 /*-----------------------------------------------------------------*/
6003 /*-----------------------------------------------------------------*/
6005 void InlineFunction(pBlock *pb)
6013 pc = setFirstItem(pb->function_calls);
6015 for( ; pc; pc = setNextItem(pb->function_calls)) {
6018 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6019 pCode *pcp = pc->prev;
6025 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 */
6027 InlineFunction(pcn->pb);
6030 At this point, *pc points to a CALL mnemonic, and
6031 *pcn points to the function that is being called.
6033 To in-line this call, we need to remove the CALL
6034 and RETURN(s), and link the function pCode in with
6041 /* Check if previous instruction was a bit skip */
6042 if (isPCI_BITSKIP(pcp)) {
6044 /* Invert skip instruction and add a goto */
6045 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6047 if(isPCL(pc_call->next)) { // Label pcode
6048 pcl = PCL(pc_call->next);
6049 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6050 pcl = PCL(PCI(pc_call->next)->label->pc);
6052 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6053 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6055 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6058 /* remove callee pBlock from the pBlock linked list */
6059 removepBlock(pcn->pb);
6067 /* Remove the Function pCode */
6068 pct = findNextInstruction(pcn->next);
6070 /* Link the function with the callee */
6071 if (pcp) pcp->next = pcn->next;
6072 pcn->next->prev = pcp;
6074 /* Convert the function name into a label */
6076 pbr = Safe_calloc(1,sizeof(pBranch));
6077 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6079 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6080 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6082 /* turn all of the return's except the last into goto's */
6083 /* check case for 2 instruction pBlocks */
6084 pce = findNextInstruction(pcn->next);
6086 pCode *pce_next = findNextInstruction(pce->next);
6088 if(pce_next == NULL) {
6089 /* found the last return */
6090 pCode *pc_call_next = findNextInstruction(pc_call->next);
6092 //fprintf(stderr,"found last return\n");
6093 //pce->print(stderr,pce);
6094 pce->prev->next = pc_call->next;
6095 pc_call->next->prev = pce->prev;
6096 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6105 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6111 /*-----------------------------------------------------------------*/
6113 /*-----------------------------------------------------------------*/
6115 void InlinepCode(void)
6124 if(!functionInlining)
6127 /* Loop through all of the function definitions and count the
6128 * number of times each one is called */
6129 //fprintf(stderr,"inlining %d\n",__LINE__);
6131 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6133 pc = setFirstItem(pb->function_calls);
6135 for( ; pc; pc = setNextItem(pb->function_calls)) {
6138 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6139 if(pcn && isPCF(pcn)) {
6140 PCF(pcn)->ncalled++;
6143 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6148 //fprintf(stderr,"inlining %d\n",__LINE__);
6150 /* Now, Loop through the function definitions again, but this
6151 * time inline those functions that have only been called once. */
6153 InlineFunction(the_pFile->pbHead);
6154 //fprintf(stderr,"inlining %d\n",__LINE__);
6156 for(pb = the_pFile->pbHead; pb; pb = pb->next)