1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1; /* inline functions if nonzero */
80 int debug_verbose = 0; /* Set true to inundate .asm file */
82 // static int GpCodeSequenceNumber = 1;
85 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
86 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
88 extern void RemoveUnusedRegisters(void);
89 extern void RegsUnMapLiveRanges(void);
90 extern void BuildFlowTree(pBlock *pb);
91 extern void pCodeRegOptimizeRegUsage(int level);
92 extern int picIsInitialized(void);
94 /****************************************************************/
95 /* Forward declarations */
96 /****************************************************************/
98 void unlinkpCode(pCode *pc);
100 static void genericAnalyze(pCode *pc);
101 static void AnalyzeGOTO(pCode *pc);
102 static void AnalyzeSKIP(pCode *pc);
103 static void AnalyzeRETURN(pCode *pc);
106 static void genericDestruct(pCode *pc);
107 static void genericPrint(FILE *of,pCode *pc);
109 static void pCodePrintLabel(FILE *of, pCode *pc);
110 static void pCodePrintFunction(FILE *of, pCode *pc);
111 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
112 static char *get_op_from_instruction( pCodeInstruction *pcc);
113 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
114 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
115 int pCodePeepMatchRule(pCode *pc);
116 void pBlockStats(FILE *of, pBlock *pb);
117 pBlock *newpBlock(void);
118 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
119 void pCodeRegMapLiveRanges(pBlock *pb);
122 /****************************************************************/
123 /* PIC Instructions */
124 /****************************************************************/
126 pCodeInstruction pciADDWF = {
127 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
140 1,0, // dest, bit instruction
142 0, // literal operand
144 (PCC_W | PCC_REGISTER), // inCond
145 (PCC_REGISTER | PCC_Z) // outCond
148 pCodeInstruction pciADDFW = {
149 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
162 0,0, // dest, bit instruction
164 0, // literal operand
166 (PCC_W | PCC_REGISTER), // inCond
167 (PCC_W | PCC_Z) // outCond
170 pCodeInstruction pciADDLW = {
171 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
184 0,0, // dest, bit instruction
186 1, // literal operand
188 (PCC_W | PCC_LITERAL), // inCond
189 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
192 pCodeInstruction pciANDLW = {
193 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
206 0,0, // dest, bit instruction
208 1, // literal operand
210 (PCC_W | PCC_LITERAL), // inCond
211 (PCC_W | PCC_Z) // outCond
214 pCodeInstruction pciANDWF = {
215 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
228 1,0, // dest, bit instruction
230 0, // literal operand
232 (PCC_W | PCC_REGISTER), // inCond
233 (PCC_REGISTER | PCC_Z) // outCond
236 pCodeInstruction pciANDFW = {
237 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
250 0,0, // dest, bit instruction
252 0, // literal operand
254 (PCC_W | PCC_REGISTER), // inCond
255 (PCC_W | PCC_Z) // outCond
258 pCodeInstruction pciBCF = {
259 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
272 1,1, // dest, bit instruction
274 0, // literal operand
276 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
277 PCC_REGISTER // outCond
280 pCodeInstruction pciBSF = {
281 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
294 1,1, // dest, bit instruction
296 0, // literal operand
298 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
299 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
302 pCodeInstruction pciBTFSC = {
303 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
316 0,1, // dest, bit instruction
318 0, // literal operand
320 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
321 PCC_EXAMINE_PCOP // outCond
324 pCodeInstruction pciBTFSS = {
325 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
338 0,1, // dest, bit instruction
340 0, // literal operand
342 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
343 PCC_EXAMINE_PCOP // outCond
346 pCodeInstruction pciCALL = {
347 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
360 0,0, // dest, bit instruction
362 0, // literal operand
368 pCodeInstruction pciCOMF = {
369 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
382 1,0, // dest, bit instruction
384 0, // literal operand
386 PCC_REGISTER, // inCond
387 PCC_REGISTER // outCond
390 pCodeInstruction pciCOMFW = {
391 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
404 0,0, // dest, bit instruction
406 0, // literal operand
408 PCC_REGISTER, // inCond
412 pCodeInstruction pciCLRF = {
413 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
426 0,0, // dest, bit instruction
428 0, // literal operand
431 PCC_REGISTER // outCond
434 pCodeInstruction pciCLRW = {
435 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
448 0,0, // dest, bit instruction
450 0, // literal operand
456 pCodeInstruction pciCLRWDT = {
457 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
470 0,0, // dest, bit instruction
472 0, // literal operand
478 pCodeInstruction pciDECF = {
479 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
492 1,0, // dest, bit instruction
494 0, // literal operand
496 PCC_REGISTER, // inCond
497 PCC_REGISTER // outCond
500 pCodeInstruction pciDECFW = {
501 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 PCC_REGISTER, // inCond
522 pCodeInstruction pciDECFSZ = {
523 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
536 1,0, // dest, bit instruction
538 0, // literal operand
540 PCC_REGISTER, // inCond
541 PCC_REGISTER // outCond
544 pCodeInstruction pciDECFSZW = {
545 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
558 0,0, // dest, bit instruction
560 0, // literal operand
562 PCC_REGISTER, // inCond
566 pCodeInstruction pciGOTO = {
567 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
580 0,0, // dest, bit instruction
582 0, // literal operand
588 pCodeInstruction pciINCF = {
589 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
602 1,0, // dest, bit instruction
604 0, // literal operand
606 PCC_REGISTER, // inCond
607 PCC_REGISTER // outCond
610 pCodeInstruction pciINCFW = {
611 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
624 0,0, // dest, bit instruction
626 0, // literal operand
628 PCC_REGISTER, // inCond
632 pCodeInstruction pciINCFSZ = {
633 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
646 1,0, // dest, bit instruction
648 0, // literal operand
650 PCC_REGISTER, // inCond
651 PCC_REGISTER // outCond
654 pCodeInstruction pciINCFSZW = {
655 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
668 0,0, // dest, bit instruction
670 0, // literal operand
672 PCC_REGISTER, // inCond
676 pCodeInstruction pciIORWF = {
677 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
690 1,0, // dest, bit instruction
692 0, // literal operand
694 (PCC_W | PCC_REGISTER), // inCond
695 (PCC_REGISTER | PCC_Z) // outCond
698 pCodeInstruction pciIORFW = {
699 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
712 0,0, // dest, bit instruction
714 0, // literal operand
716 (PCC_W | PCC_REGISTER), // inCond
717 (PCC_W | PCC_Z) // outCond
720 pCodeInstruction pciIORLW = {
721 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
734 0,0, // dest, bit instruction
736 1, // literal operand
738 (PCC_W | PCC_LITERAL), // inCond
739 (PCC_W | PCC_Z) // outCond
742 pCodeInstruction pciMOVF = {
743 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
756 1,0, // dest, bit instruction
758 0, // literal operand
760 PCC_REGISTER, // inCond
764 pCodeInstruction pciMOVFW = {
765 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
778 0,0, // dest, bit instruction
780 0, // literal operand
782 PCC_REGISTER, // inCond
783 (PCC_W | PCC_Z) // outCond
786 pCodeInstruction pciMOVWF = {
787 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
800 0,0, // dest, bit instruction
802 0, // literal operand
805 PCC_REGISTER // outCond
808 pCodeInstruction pciMOVLW = {
809 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
821 0,0, // dest, bit instruction
823 1, // literal operand
825 (PCC_NONE | PCC_LITERAL), // inCond
829 pCodeInstruction pciNOP = {
830 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
842 0,0, // dest, bit instruction
844 0, // literal operand
850 pCodeInstruction pciRETFIE = {
851 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
864 0,0, // dest, bit instruction
866 0, // literal operand
869 PCC_NONE // outCond (not true... affects the GIE bit too)
872 pCodeInstruction pciRETLW = {
873 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
886 0,0, // dest, bit instruction
888 1, // literal operand
890 PCC_LITERAL, // inCond
894 pCodeInstruction pciRETURN = {
895 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
908 0,0, // dest, bit instruction
910 0, // literal operand
916 pCodeInstruction pciRLF = {
917 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
930 1,0, // dest, bit instruction
932 0, // literal operand
934 (PCC_C | PCC_REGISTER), // inCond
935 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
938 pCodeInstruction pciRLFW = {
939 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
952 0,0, // dest, bit instruction
954 0, // literal operand
956 (PCC_C | PCC_REGISTER), // inCond
957 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
960 pCodeInstruction pciRRF = {
961 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
974 1,0, // dest, bit instruction
976 0, // literal operand
978 (PCC_C | PCC_REGISTER), // inCond
979 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
982 pCodeInstruction pciRRFW = {
983 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
996 0,0, // dest, bit instruction
998 0, // literal operand
1000 (PCC_C | PCC_REGISTER), // inCond
1001 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1004 pCodeInstruction pciSUBWF = {
1005 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1011 NULL, // from branch
1018 1,0, // dest, bit instruction
1019 0,0, // branch, skip
1020 0, // literal operand
1022 (PCC_W | PCC_REGISTER), // inCond
1023 (PCC_REGISTER | PCC_Z) // outCond
1026 pCodeInstruction pciSUBFW = {
1027 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1033 NULL, // from branch
1040 0,0, // dest, bit instruction
1041 0,0, // branch, skip
1042 0, // literal operand
1044 (PCC_W | PCC_REGISTER), // inCond
1045 (PCC_W | PCC_Z) // outCond
1048 pCodeInstruction pciSUBLW = {
1049 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1055 NULL, // from branch
1062 0,0, // dest, bit instruction
1063 0,0, // branch, skip
1064 1, // literal operand
1066 (PCC_W | PCC_LITERAL), // inCond
1067 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1070 pCodeInstruction pciSWAPF = {
1071 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1077 NULL, // from branch
1084 1,0, // dest, bit instruction
1085 0,0, // branch, skip
1086 0, // literal operand
1088 (PCC_REGISTER), // inCond
1089 (PCC_REGISTER) // outCond
1092 pCodeInstruction pciSWAPFW = {
1093 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1099 NULL, // from branch
1106 0,0, // dest, bit instruction
1107 0,0, // branch, skip
1108 0, // literal operand
1110 (PCC_REGISTER), // inCond
1114 pCodeInstruction pciTRIS = {
1115 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1121 NULL, // from branch
1128 0,0, // dest, bit instruction
1129 0,0, // branch, skip
1130 0, // literal operand
1133 PCC_REGISTER // outCond
1136 pCodeInstruction pciXORWF = {
1137 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1143 NULL, // from branch
1150 1,0, // dest, bit instruction
1151 0,0, // branch, skip
1152 0, // literal operand
1154 (PCC_W | PCC_REGISTER), // inCond
1155 (PCC_REGISTER | PCC_Z) // outCond
1158 pCodeInstruction pciXORFW = {
1159 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1165 NULL, // from branch
1172 0,0, // dest, bit instruction
1173 0,0, // branch, skip
1174 0, // literal operand
1176 (PCC_W | PCC_REGISTER), // inCond
1177 (PCC_W | PCC_Z) // outCond
1180 pCodeInstruction pciXORLW = {
1181 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1187 NULL, // from branch
1194 0,0, // dest, bit instruction
1195 0,0, // branch, skip
1196 1, // literal operand
1198 (PCC_W | PCC_LITERAL), // inCond
1199 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1203 pCodeInstruction pciBANKSEL = {
1204 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1210 NULL, // from branch
1217 0,0, // dest, bit instruction
1218 0,0, // branch, skip
1219 0, // literal operand
1222 PCC_REGISTER // outCond
1225 pCodeInstruction pciPAGESEL = {
1226 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1232 NULL, // from branch
1239 0,0, // dest, bit instruction
1240 0,0, // branch, skip
1241 0, // literal operand
1244 PCC_REGISTER // outCond
1247 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1250 /*-----------------------------------------------------------------*/
1251 /* return a unique ID number to assist pCodes debuging */
1252 /*-----------------------------------------------------------------*/
1253 unsigned PCodeID(void) {
1254 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1256 static unsigned int stop;
1257 if (pcodeId == 5801)
1259 if ((pcodeId >= 855)&&(pcodeId <= 856))
1265 #ifdef HAVE_VSNPRINTF
1266 // Alas, vsnprintf is not ANSI standard, and does not exist
1267 // on Solaris (and probably other non-Gnu flavored Unixes).
1269 /*-----------------------------------------------------------------*/
1270 /* SAFE_snprintf - like snprintf except the string pointer is */
1271 /* after the string has been printed to. This is */
1272 /* useful for printing to string as though if it */
1273 /* were a stream. */
1274 /*-----------------------------------------------------------------*/
1275 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1283 va_start(val, format);
1285 vsnprintf(*str, *size, format, val);
1290 if((size_t)len > *size) {
1291 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1292 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1300 #else // HAVE_VSNPRINTF
1302 // This version is *not* safe, despite the name.
1304 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1308 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1313 va_start(val, format);
1315 vsprintf(buffer, format, val);
1318 len = strlen(buffer);
1320 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1321 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1324 strcpy(*str, buffer);
1330 #endif // HAVE_VSNPRINTF
1333 extern void initStack(int base_address, int size);
1334 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1335 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1336 extern void init_pic(char *);
1338 void pCodeInitRegisters(void)
1340 static int initialized=0;
1341 int shareBankAddress,stkSize;
1347 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1348 stkSize = 8; // Set pseudo stack size to 8
1349 initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters
1350 init_pic(port->processor);
1352 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1353 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1354 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1355 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1356 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1357 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1359 pc_status.rIdx = IDX_STATUS;
1360 pc_fsr.rIdx = IDX_FSR;
1361 pc_indf.rIdx = IDX_INDF;
1362 pc_intcon.rIdx = IDX_INTCON;
1363 pc_pcl.rIdx = IDX_PCL;
1364 pc_pclath.rIdx = IDX_PCLATH;
1366 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. */
1367 pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1368 pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1370 pc_wsave.rIdx = pc_wsave.r->rIdx;
1371 pc_ssave.rIdx = pc_ssave.r->rIdx;
1372 pc_psave.rIdx = pc_psave.r->rIdx;
1374 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1375 pc_wsave.r->address = shareBankAddress-stkSize;
1376 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1377 pc_ssave.r->address = shareBankAddress-stkSize-1;
1378 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1379 pc_psave.r->address = shareBankAddress-stkSize-2;
1381 /* probably should put this in a separate initialization routine */
1382 pb_dead_pcodes = newpBlock();
1386 /*-----------------------------------------------------------------*/
1387 /* mnem2key - convert a pic mnemonic into a hash key */
1388 /* (BTW - this spreads the mnemonics quite well) */
1390 /*-----------------------------------------------------------------*/
1392 int mnem2key(char const *mnem)
1401 key += toupper(*mnem++) +1;
1405 return (key & 0x1f);
1409 void pic14initMnemonics(void)
1414 pCodeInstruction *pci;
1416 if(mnemonics_initialized)
1419 //FIXME - probably should NULL out the array before making the assignments
1420 //since we check the array contents below this initialization.
1422 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1423 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1424 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1425 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1426 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1427 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1428 pic14Mnemonics[POC_BCF] = &pciBCF;
1429 pic14Mnemonics[POC_BSF] = &pciBSF;
1430 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1431 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1432 pic14Mnemonics[POC_CALL] = &pciCALL;
1433 pic14Mnemonics[POC_COMF] = &pciCOMF;
1434 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1435 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1436 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1437 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1438 pic14Mnemonics[POC_DECF] = &pciDECF;
1439 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1440 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1441 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1442 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1443 pic14Mnemonics[POC_INCF] = &pciINCF;
1444 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1445 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1446 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1447 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1448 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1449 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1450 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1451 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1452 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1453 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1454 pic14Mnemonics[POC_NOP] = &pciNOP;
1455 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1456 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1457 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1458 pic14Mnemonics[POC_RLF] = &pciRLF;
1459 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1460 pic14Mnemonics[POC_RRF] = &pciRRF;
1461 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1462 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1463 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1464 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1465 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1466 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1467 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1468 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1469 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1470 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1471 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1472 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1474 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1475 if(pic14Mnemonics[i])
1476 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1477 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1480 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1481 pci = hTabNextItem(pic14MnemonicsHash, &key);
1484 mnemonics_initialized = 1;
1487 int getpCodePeepCommand(char *cmd);
1489 int getpCode(char *mnem,unsigned dest)
1492 pCodeInstruction *pci;
1493 int key = mnem2key(mnem);
1495 if(!mnemonics_initialized)
1496 pic14initMnemonics();
1498 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1502 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1503 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1507 pci = hTabNextItemWK (pic14MnemonicsHash);
1514 /*-----------------------------------------------------------------*
1515 * pic14initpCodePeepCommands
1517 *-----------------------------------------------------------------*/
1518 void pic14initpCodePeepCommands(void)
1526 hTabAddItem(&pic14pCodePeepCommandsHash,
1527 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1529 } while (peepCommands[i].cmd);
1531 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1534 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1535 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1540 /*-----------------------------------------------------------------
1543 *-----------------------------------------------------------------*/
1545 int getpCodePeepCommand(char *cmd)
1549 int key = mnem2key(cmd);
1552 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1555 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1556 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1560 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1567 char getpBlock_dbName(pBlock *pb)
1573 return pb->cmemmap->dbName;
1577 void pBlockConvert2ISR(pBlock *pb)
1588 /*-----------------------------------------------------------------*/
1589 /* movepBlock2Head - given the dbname of a pBlock, move all */
1590 /* instances to the front of the doubly linked */
1591 /* list of pBlocks */
1592 /*-----------------------------------------------------------------*/
1594 void movepBlock2Head(char dbName)
1601 pb = the_pFile->pbHead;
1605 if(getpBlock_dbName(pb) == dbName) {
1606 pBlock *pbn = pb->next;
1607 pb->next = the_pFile->pbHead;
1608 the_pFile->pbHead->prev = pb;
1609 the_pFile->pbHead = pb;
1612 pb->prev->next = pbn;
1614 // If the pBlock that we just moved was the last
1615 // one in the link of all of the pBlocks, then we
1616 // need to point the tail to the block just before
1617 // the one we moved.
1618 // Note: if pb->next is NULL, then pb must have
1619 // been the last pBlock in the chain.
1622 pbn->prev = pb->prev;
1624 the_pFile->pbTail = pb->prev;
1635 void copypCode(FILE *of, char dbName)
1639 if(!of || !the_pFile)
1642 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1643 if(getpBlock_dbName(pb) == dbName) {
1651 void pcode_test(void)
1654 DFPRINTF((stderr,"pcode is alive!\n"));
1664 /* create the file name */
1665 strcpy(buffer,dstFileName);
1666 strcat(buffer,".p");
1668 if( !(pFile = fopen(buffer, "w" ))) {
1669 werror(E_FILE_OPEN_ERR,buffer);
1673 fprintf(pFile,"pcode dump\n\n");
1675 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1676 fprintf(pFile,"\n\tNew pBlock\n\n");
1678 fprintf(pFile,"%s",pb->cmemmap->sname);
1680 fprintf(pFile,"internal pblock");
1682 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1683 printpBlock(pFile,pb);
1687 /*-----------------------------------------------------------------*/
1688 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1689 /* ister, RegCond will return the bit being referenced. */
1691 /* fixme - why not just OR in the pcop bit field */
1692 /*-----------------------------------------------------------------*/
1694 static int RegCond(pCodeOp *pcop)
1700 if (pcop->type == PO_GPR_BIT) {
1701 char *name = pcop->name;
1703 name = PCOR(pcop)->r->name;
1704 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1705 switch(PCORB(pcop)->bit) {
1719 /*-----------------------------------------------------------------*/
1720 /* newpCode - create and return a newly initialized pCode */
1722 /* fixme - rename this */
1724 /* The purpose of this routine is to create a new Instruction */
1725 /* pCode. This is called by gen.c while the assembly code is being */
1729 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1730 /* (note that the op is analogous to but not the */
1731 /* same thing as the opcode of the instruction.) */
1732 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1735 /* a pointer to the new malloc'd pCode is returned. */
1739 /*-----------------------------------------------------------------*/
1740 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1742 pCodeInstruction *pci ;
1744 if(!mnemonics_initialized)
1745 pic14initMnemonics();
1747 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1749 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1750 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1751 pci->pc.id = PCodeID();
1754 if(pci->inCond & PCC_EXAMINE_PCOP)
1755 pci->inCond |= RegCond(pcop);
1757 if(pci->outCond & PCC_EXAMINE_PCOP)
1758 pci->outCond |= RegCond(pcop);
1760 pci->pc.prev = pci->pc.next = NULL;
1761 return (pCode *)pci;
1764 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1770 /*-----------------------------------------------------------------*/
1771 /* newpCodeWild - create a "wild" as in wild card pCode */
1773 /* Wild pcodes are used during the peep hole optimizer to serve */
1774 /* as place holders for any instruction. When a snippet of code is */
1775 /* compared to a peep hole rule, the wild card opcode will match */
1776 /* any instruction. However, the optional operand and label are */
1777 /* additional qualifiers that must also be matched before the */
1778 /* line (of assembly code) is declared matched. Note that the */
1779 /* operand may be wild too. */
1781 /* Note, a wild instruction is specified just like a wild var: */
1782 /* %4 ; A wild instruction, */
1783 /* See the peeph.def file for additional examples */
1785 /*-----------------------------------------------------------------*/
1787 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1792 pcw = Safe_calloc(1,sizeof(pCodeWild));
1794 pcw->pci.pc.type = PC_WILD;
1795 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1796 pcw->id = PCodeID();
1797 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1798 pcw->pci.pc.pb = NULL;
1800 // pcw->pci.pc.analyze = genericAnalyze;
1801 pcw->pci.pc.destruct = genericDestruct;
1802 pcw->pci.pc.print = genericPrint;
1804 pcw->id = pCodeID; // this is the 'n' in %n
1805 pcw->operand = optional_operand;
1806 pcw->label = optional_label;
1808 pcw->mustBeBitSkipInst = 0;
1809 pcw->mustNotBeBitSkipInst = 0;
1810 pcw->invertBitSkipInst = 0;
1812 return ( (pCode *)pcw);
1816 /*-----------------------------------------------------------------*/
1817 /* newPcodeInlineP - create a new pCode from a char string */
1818 /*-----------------------------------------------------------------*/
1821 pCode *newpCodeInlineP(char *cP)
1826 pcc = Safe_calloc(1,sizeof(pCodeComment));
1828 pcc->pc.type = PC_INLINE;
1829 pcc->pc.prev = pcc->pc.next = NULL;
1830 pcc->pc.id = PCodeID();
1831 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1834 // pcc->pc.analyze = genericAnalyze;
1835 pcc->pc.destruct = genericDestruct;
1836 pcc->pc.print = genericPrint;
1839 pcc->comment = Safe_strdup(cP);
1841 pcc->comment = NULL;
1843 return ( (pCode *)pcc);
1847 /*-----------------------------------------------------------------*/
1848 /* newPcodeCharP - create a new pCode from a char string */
1849 /*-----------------------------------------------------------------*/
1851 pCode *newpCodeCharP(char *cP)
1856 pcc = Safe_calloc(1,sizeof(pCodeComment));
1858 pcc->pc.type = PC_COMMENT;
1859 pcc->pc.prev = pcc->pc.next = NULL;
1860 pcc->pc.id = PCodeID();
1861 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1864 // pcc->pc.analyze = genericAnalyze;
1865 pcc->pc.destruct = genericDestruct;
1866 pcc->pc.print = genericPrint;
1869 pcc->comment = Safe_strdup(cP);
1871 pcc->comment = NULL;
1873 return ( (pCode *)pcc);
1877 /*-----------------------------------------------------------------*/
1878 /* newpCodeFunction - */
1879 /*-----------------------------------------------------------------*/
1882 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1886 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1887 //_ALLOC(pcf,sizeof(pCodeFunction));
1889 pcf->pc.type = PC_FUNCTION;
1890 pcf->pc.prev = pcf->pc.next = NULL;
1891 pcf->pc.id = PCodeID();
1892 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1895 // pcf->pc.analyze = genericAnalyze;
1896 pcf->pc.destruct = genericDestruct;
1897 pcf->pc.print = pCodePrintFunction;
1902 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1903 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1904 strcpy(pcf->modname,mod);
1906 pcf->modname = NULL;
1909 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1910 pcf->fname = Safe_calloc(1,strlen(f)+1);
1911 strcpy(pcf->fname,f);
1915 pcf->isPublic = (unsigned)isPublic;
1917 return ( (pCode *)pcf);
1921 /*-----------------------------------------------------------------*/
1923 /*-----------------------------------------------------------------*/
1924 void destructpCodeFlow(pCode *pc)
1926 if(!pc || !isPCFL(pc))
1935 deleteSet(&PCFL(pc)->registers);
1936 deleteSet(&PCFL(pc)->from);
1937 deleteSet(&PCFL(pc)->to);
1942 pCode *newpCodeFlow(void )
1946 //_ALLOC(pcflow,sizeof(pCodeFlow));
1947 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1949 pcflow->pc.type = PC_FLOW;
1950 pcflow->pc.prev = pcflow->pc.next = NULL;
1951 pcflow->pc.pb = NULL;
1953 // pcflow->pc.analyze = genericAnalyze;
1954 pcflow->pc.destruct = destructpCodeFlow;
1955 pcflow->pc.print = genericPrint;
1957 pcflow->pc.seq = GpcFlowSeq++;
1959 pcflow->from = pcflow->to = NULL;
1961 pcflow->inCond = PCC_NONE;
1962 pcflow->outCond = PCC_NONE;
1964 pcflow->firstBank = 'U'; /* Undetermined */
1965 pcflow->lastBank = 'U'; /* Undetermined */
1967 pcflow->FromConflicts = 0;
1968 pcflow->ToConflicts = 0;
1972 pcflow->registers = newSet();
1974 return ( (pCode *)pcflow);
1978 /*-----------------------------------------------------------------*/
1979 /*-----------------------------------------------------------------*/
1980 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1982 pCodeFlowLink *pcflowLink;
1984 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1986 pcflowLink->pcflow = pcflow;
1987 pcflowLink->bank_conflict = 0;
1992 /*-----------------------------------------------------------------*/
1993 /* newpCodeCSource - create a new pCode Source Symbol */
1994 /*-----------------------------------------------------------------*/
1996 pCode *newpCodeCSource(int ln, char *f, char *l)
2001 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2003 pccs->pc.type = PC_CSOURCE;
2004 pccs->pc.prev = pccs->pc.next = NULL;
2005 pccs->pc.id = PCodeID();
2008 pccs->pc.destruct = genericDestruct;
2009 pccs->pc.print = genericPrint;
2011 pccs->line_number = ln;
2013 pccs->line = Safe_strdup(l);
2018 pccs->file_name = Safe_strdup(f);
2020 pccs->file_name = NULL;
2022 return ( (pCode *)pccs);
2025 /*-----------------------------------------------------------------*/
2026 /* pCodeLabelDestruct - free memory used by a label. */
2027 /*-----------------------------------------------------------------*/
2028 static void pCodeLabelDestruct(pCode *pc)
2034 if((pc->type == PC_LABEL) && PCL(pc)->label)
2035 free(PCL(pc)->label);
2041 pCode *newpCodeLabel(char *name, int key)
2047 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2049 pcl->pc.type = PC_LABEL;
2050 pcl->pc.prev = pcl->pc.next = NULL;
2051 pcl->pc.id = PCodeID();
2052 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2055 // pcl->pc.analyze = genericAnalyze;
2056 pcl->pc.destruct = pCodeLabelDestruct;
2057 pcl->pc.print = pCodePrintLabel;
2063 sprintf(s,"_%05d_DS_",key);
2068 pcl->label = Safe_strdup(s);
2070 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2071 return ( (pCode *)pcl);
2076 /*-----------------------------------------------------------------*/
2077 /* newpBlock - create and return a pointer to a new pBlock */
2078 /*-----------------------------------------------------------------*/
2079 pBlock *newpBlock(void)
2084 PpB = Safe_calloc(1,sizeof(pBlock) );
2085 PpB->next = PpB->prev = NULL;
2087 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2088 PpB->tregisters = NULL;
2090 PpB->FlowTree = NULL;
2096 /*-----------------------------------------------------------------*/
2097 /* newpCodeChain - create a new chain of pCodes */
2098 /*-----------------------------------------------------------------*
2100 * This function will create a new pBlock and the pointer to the
2101 * pCode that is passed in will be the first pCode in the block.
2102 *-----------------------------------------------------------------*/
2105 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2108 pBlock *pB = newpBlock();
2110 pB->pcHead = pB->pcTail = pc;
2117 /*-----------------------------------------------------------------*/
2118 /* newpCodeOpLabel - Create a new label given the key */
2119 /* Note, a negative key means that the label is part of wild card */
2120 /* (and hence a wild card label) used in the pCodePeep */
2121 /* optimizations). */
2122 /*-----------------------------------------------------------------*/
2124 pCodeOp *newpCodeOpLabel(char *name, int key)
2127 static int label_key=-1;
2131 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2132 pcop->type = PO_LABEL;
2137 sprintf(s=buffer,"_%05d_DS_",key);
2139 s = name, key = label_key--;
2141 PCOLAB(pcop)->offset = 0;
2143 pcop->name = Safe_strdup(s);
2145 ((pCodeOpLabel *)pcop)->key = key;
2147 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2151 /*-----------------------------------------------------------------*/
2152 /*-----------------------------------------------------------------*/
2153 pCodeOp *newpCodeOpLit(int lit)
2159 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2160 pcop->type = PO_LITERAL;
2164 sprintf(s,"0x%02x",lit);
2166 pcop->name = Safe_strdup(s);
2169 ((pCodeOpLit *)pcop)->lit = lit;
2174 /*-----------------------------------------------------------------*/
2175 /*-----------------------------------------------------------------*/
2176 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2180 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2181 pcop->type = PO_IMMEDIATE;
2184 pcop->name = Safe_strdup(name);
2187 r = dirregWithName(name);
2191 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2192 PCOI(pcop)->rIdx = r->rIdx;
2194 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2195 PCOI(pcop)->rIdx = -1;
2197 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2202 PCOI(pcop)->index = index;
2203 PCOI(pcop)->offset = offset;
2204 PCOI(pcop)->_const = code_space;
2205 PCOI(pcop)->_function = is_func;
2210 /*-----------------------------------------------------------------*/
2211 /*-----------------------------------------------------------------*/
2212 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2218 if(!pcwb || !subtype) {
2219 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2223 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2224 pcop->type = PO_WILD;
2225 sprintf(s,"%%%d",id);
2226 pcop->name = Safe_strdup(s);
2228 PCOW(pcop)->id = id;
2229 PCOW(pcop)->pcwb = pcwb;
2230 PCOW(pcop)->subtype = subtype;
2231 PCOW(pcop)->matched = NULL;
2235 /*-----------------------------------------------------------------*/
2236 /* Find a symbol with matching name */
2237 /*-----------------------------------------------------------------*/
2238 static symbol *symFindWithName(memmap * map, const char *name)
2242 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2243 if (sym->rname && (strcmp(sym->rname,name)==0))
2249 /*-----------------------------------------------------------------*/
2250 /*-----------------------------------------------------------------*/
2251 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2256 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2257 pcop->type = PO_GPR_BIT;
2259 PCORB(pcop)->bit = ibit;
2260 PCORB(pcop)->inBitSpace = inBitSpace;
2262 if (name) r = regFindWithName(name);
2264 // Register has not been allocated - check for symbol information
2266 sym = symFindWithName(bit, name);
2267 if (!sym) sym = symFindWithName(sfrbit, name);
2268 if (!sym) sym = symFindWithName(sfr, name);
2270 r = allocNewDirReg(sym->etype,name);
2276 PCOR(pcop)->rIdx = r->rIdx;
2278 pcop->name = Safe_strdup(name);
2279 PCOR(pcop)->r = NULL;
2280 PCOR(pcop)->rIdx = 0;
2285 /*-----------------------------------------------------------------*
2286 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2288 * If rIdx >=0 then a specific register from the set of registers
2289 * will be selected. If rIdx <0, then a new register will be searched
2291 *-----------------------------------------------------------------*/
2293 pCodeOp *newpCodeOpReg(int rIdx)
2297 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2302 PCOR(pcop)->rIdx = rIdx;
2303 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2305 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2308 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2312 pcop->type = PCOR(pcop)->r->pc_type;
2317 pCodeOp *newpCodeOpRegFromStr(char *name)
2321 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2322 PCOR(pcop)->r = allocRegByName(name, 1);
2323 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2324 pcop->type = PCOR(pcop)->r->pc_type;
2325 pcop->name = PCOR(pcop)->r->name;
2330 pCodeOp *newpCodeOpStr(char *name)
2334 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2335 pcop->type = PO_STR;
2336 pcop->name = Safe_strdup(name);
2338 PCOS(pcop)->isPublic = 0;
2344 /*-----------------------------------------------------------------*/
2345 /*-----------------------------------------------------------------*/
2347 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2354 pcop = newpCodeOpBit(name, -1,0);
2358 pcop = newpCodeOpLit(-1);
2362 pcop = newpCodeOpLabel(NULL,-1);
2366 pcop = newpCodeOpReg(-1);
2369 case PO_GPR_POINTER:
2370 case PO_GPR_REGISTER:
2372 pcop = newpCodeOpRegFromStr(name);
2374 pcop = newpCodeOpReg(-1);
2378 pcop = newpCodeOpStr(name);
2382 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2385 pcop->name = Safe_strdup(name);
2393 /*-----------------------------------------------------------------*/
2394 /*-----------------------------------------------------------------*/
2395 void pCodeConstString(char *name, char *value)
2399 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2404 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2408 sprintf(buffer,"; %s = %s",name,value);
2410 addpCode2pBlock(pb,newpCodeCharP(buffer));
2411 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2414 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2420 /*-----------------------------------------------------------------*/
2421 /*-----------------------------------------------------------------*/
2422 void pCodeReadCodeTable(void)
2426 fprintf(stderr, " %s\n",__FUNCTION__);
2428 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2432 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2433 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2434 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2435 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2437 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2438 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2439 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2440 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2445 /*-----------------------------------------------------------------*/
2446 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2447 /*-----------------------------------------------------------------*/
2448 void addpCode2pBlock(pBlock *pb, pCode *pc)
2455 /* If this is the first pcode to be added to a block that
2456 * was initialized with a NULL pcode, then go ahead and
2457 * make this pcode the head and tail */
2458 pb->pcHead = pb->pcTail = pc;
2461 pb->pcTail->next = pc;
2463 pc->prev = pb->pcTail;
2470 /*-----------------------------------------------------------------*/
2471 /* addpBlock - place a pBlock into the pFile */
2472 /*-----------------------------------------------------------------*/
2473 void addpBlock(pBlock *pb)
2475 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2478 /* First time called, we'll pass through here. */
2479 //_ALLOC(the_pFile,sizeof(pFile));
2480 the_pFile = Safe_calloc(1,sizeof(pFile));
2481 the_pFile->pbHead = the_pFile->pbTail = pb;
2482 the_pFile->functions = NULL;
2486 the_pFile->pbTail->next = pb;
2487 pb->prev = the_pFile->pbTail;
2489 the_pFile->pbTail = pb;
2492 /*-----------------------------------------------------------------*/
2493 /* removepBlock - remove a pBlock from the pFile */
2494 /*-----------------------------------------------------------------*/
2495 void removepBlock(pBlock *pb)
2503 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2505 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2508 if(pbs == the_pFile->pbHead)
2509 the_pFile->pbHead = pbs->next;
2511 if (pbs == the_pFile->pbTail)
2512 the_pFile->pbTail = pbs->prev;
2515 pbs->next->prev = pbs->prev;
2518 pbs->prev->next = pbs->next;
2525 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2529 /*-----------------------------------------------------------------*/
2530 /* printpCode - write the contents of a pCode to a file */
2531 /*-----------------------------------------------------------------*/
2532 void printpCode(FILE *of, pCode *pc)
2543 fprintf(of,"warning - unable to print pCode\n");
2546 /*-----------------------------------------------------------------*/
2547 /* printpBlock - write the contents of a pBlock to a file */
2548 /*-----------------------------------------------------------------*/
2549 void printpBlock(FILE *of, pBlock *pb)
2559 for(pc = pb->pcHead; pc; pc = pc->next)
2564 /*-----------------------------------------------------------------*/
2566 /* pCode processing */
2570 /*-----------------------------------------------------------------*/
2572 void unlinkpCode(pCode *pc)
2578 fprintf(stderr,"Unlinking: ");
2579 printpCode(stderr, pc);
2582 pc->prev->next = pc->next;
2584 pc->next->prev = pc->prev;
2586 pc->prev = pc->next = NULL;
2590 /*-----------------------------------------------------------------*/
2591 /*-----------------------------------------------------------------*/
2593 static void genericDestruct(pCode *pc)
2599 /* For instructions, tell the register (if there's one used)
2600 * that it's no longer needed */
2601 regs *reg = getRegFromInstruction(pc);
2603 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2606 /* Instead of deleting the memory used by this pCode, mark
2607 * the object as bad so that if there's a pointer to this pCode
2608 * dangling around somewhere then (hopefully) when the type is
2609 * checked we'll catch it.
2614 addpCode2pBlock(pb_dead_pcodes, pc);
2621 /*-----------------------------------------------------------------*/
2622 /* Copies the pCodeInstruction flow pointer from source pCode */
2623 /*-----------------------------------------------------------------*/
2624 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2626 pCodeFlow *pcflow = 0;
2627 for (p=pcs; p; p=p->prev) {
2629 pcflow = PCI(p)->pcflow;
2633 pcflow = (pCodeFlow*)p;
2637 PCI(pcd)->pcflow = pcflow;
2640 /*-----------------------------------------------------------------*/
2641 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2642 /* into the pCode chain containing pc1 */
2643 /*-----------------------------------------------------------------*/
2644 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2650 pc2->next = pc1->next;
2652 pc1->next->prev = pc2;
2658 /* If this is an instrution type propogate the flow */
2660 CopyFlow(PCI(pc2),pc1);
2663 /*------------------------------------------------------------------*/
2664 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2665 /* into the pCode chain containing pc1 */
2666 /*------------------------------------------------------------------*/
2667 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2673 pc2->prev = pc1->prev;
2675 pc1->prev->next = pc2;
2681 /* If this is an instrution type propogate the flow */
2683 CopyFlow(PCI(pc2),pc1);
2686 /*-----------------------------------------------------------------*/
2687 /* pCodeOpCopy - copy a pcode operator */
2688 /*-----------------------------------------------------------------*/
2689 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2691 pCodeOp *pcopnew=NULL;
2696 switch(pcop->type) {
2699 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2700 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2701 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2702 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2707 /* Here we expand the wild card into the appropriate type: */
2708 /* By recursively calling pCodeOpCopy */
2709 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2710 if(PCOW(pcop)->matched)
2711 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2714 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2715 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2716 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2723 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2724 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2725 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2729 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2730 PCOI(pcopnew)->index = PCOI(pcop)->index;
2731 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2732 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2733 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2737 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2738 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2739 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2744 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2745 PCOR(pcopnew)->r = PCOR(pcop)->r;
2746 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2747 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2751 case PO_GPR_POINTER:
2752 case PO_GPR_REGISTER:
2756 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2757 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2758 PCOR(pcopnew)->r = PCOR(pcop)->r;
2759 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2760 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2761 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2765 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2766 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2767 PCOR(pcopnew)->r = PCOR(pcop)->r;
2768 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2769 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2772 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2773 case PO_SFR_REGISTER:
2781 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2782 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2786 pcopnew->type = pcop->type;
2788 pcopnew->name = Safe_strdup(pcop->name);
2790 pcopnew->name = NULL;
2795 /*-----------------------------------------------------------------*/
2796 /* popCopyReg - copy a pcode operator */
2797 /*-----------------------------------------------------------------*/
2798 pCodeOp *popCopyReg(pCodeOpReg *pc)
2802 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2803 pcor->pcop.type = pc->pcop.type;
2805 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2806 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2808 pcor->pcop.name = NULL;
2811 pcor->rIdx = pc->rIdx;
2814 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2819 /*-----------------------------------------------------------------*/
2820 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2821 /*-----------------------------------------------------------------*/
2822 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2824 pCodeInstruction *new_pci;
2827 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2829 new_pci = PCI(newpCode(pci->op,pci->pcop));
2831 new_pci->pc.pb = pci->pc.pb;
2832 new_pci->from = pci->from;
2833 new_pci->to = pci->to;
2834 new_pci->label = pci->label;
2835 new_pci->pcflow = pci->pcflow;
2837 return PCODE(new_pci);
2840 /*-----------------------------------------------------------------*/
2841 /*-----------------------------------------------------------------*/
2842 void pCodeDeleteChain(pCode *f,pCode *t)
2847 DFPRINTF((stderr,"delete pCode:\n"));
2849 //f->print(stderr,f);
2850 //f->delete(f); this dumps core...
2855 /*-----------------------------------------------------------------*/
2856 /*-----------------------------------------------------------------*/
2857 void pBlockRegs(FILE *of, pBlock *pb)
2862 r = setFirstItem(pb->tregisters);
2864 r = setNextItem(pb->tregisters);
2869 /*-----------------------------------------------------------------*/
2870 /*-----------------------------------------------------------------*/
2871 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2876 int use_buffer = 1; // copy the string to the passed buffer pointer
2881 use_buffer = 0; // Don't bother copying the string to the buffer.
2885 switch(pcop->type) {
2889 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2892 //return PCOR(pcop)->r->name;
2896 if (PCOR(pcop)->r->type == REG_STK)
2897 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2899 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2902 SAFE_snprintf(&buffer,&size,"%s",r->name);
2912 if(PCOI(pcop)->_const) {
2914 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2915 switch(PCOI(pcop)->offset) {
2917 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2920 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2923 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2926 8 * PCOI(pcop)->offset );
2929 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2932 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2933 SAFE_snprintf(&s,&size,"(%s + %d)",
2935 PCOI(pcop)->index );
2937 switch(PCOI(pcop)->offset) {
2939 SAFE_snprintf(&s,&size,"%s",pcop->name);
2942 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2945 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2954 //size = sizeof(buffer);
2955 if( PCOR(pcop)->instance) {
2956 SAFE_snprintf(&s,&size,"(%s + %d)",
2958 PCOR(pcop)->instance );
2959 //fprintf(stderr,"PO_DIR %s\n",buffer);
2961 SAFE_snprintf(&s,&size,"%s",pcop->name);
2967 if(PCOLAB(pcop)->offset == 1)
2968 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2970 SAFE_snprintf(&s,&size,"%s",pcop->name);
2977 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2986 return "NO operand";
2990 /*-----------------------------------------------------------------*/
2991 /*-----------------------------------------------------------------*/
2992 static char *get_op_from_instruction( pCodeInstruction *pcc)
2996 return get_op(pcc->pcop,NULL,0);
2998 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2999 return ("ERROR Null: "__FUNCTION__);
3001 return ("ERROR Null: get_op_from_instruction");
3005 /*-----------------------------------------------------------------*/
3006 /*-----------------------------------------------------------------*/
3007 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3010 fprintf(of,"pcodeopprint- not implemented\n");
3013 /*-----------------------------------------------------------------*/
3014 /*-----------------------------------------------------------------*/
3015 char *pCode2str(char *str, size_t size, pCode *pc)
3023 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3025 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3027 if(PCI(pc)->isBitInst) {
3028 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3029 char *name = PCI(pc)->pcop->name;
3031 name = PCOR(PCI(pc)->pcop)->r->name;
3032 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3033 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3035 SAFE_snprintf(&s,&size,"%s,%d", name,
3036 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3037 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3038 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3040 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3041 //PCI(pc)->pcop->t.bit );
3044 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3045 if( PCI(pc)->num_ops == 2)
3046 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3048 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3051 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3053 if( PCI(pc)->num_ops == 2)
3054 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3062 /* assuming that comment ends with a \n */
3063 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3067 /* assuming that inline code ends with a \n */
3068 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3072 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3075 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3078 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3081 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3084 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3088 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3095 /*-----------------------------------------------------------------*/
3096 /* genericPrint - the contents of a pCode to a file */
3097 /*-----------------------------------------------------------------*/
3098 static void genericPrint(FILE *of, pCode *pc)
3106 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3110 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3114 // If the opcode has a label, print that first
3116 pBranch *pbl = PCI(pc)->label;
3117 while(pbl && pbl->pc) {
3118 if(pbl->pc->type == PC_LABEL)
3119 pCodePrintLabel(of, pbl->pc);
3125 genericPrint(of,PCODE(PCI(pc)->cline));
3130 pCode2str(str, 256, pc);
3132 fprintf(of,"%s",str);
3136 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3138 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3143 pBranch *dpb = pc->to; // debug
3145 switch ( dpb->pc->type) {
3147 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3150 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3153 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3156 fprintf(of, "\t;flow");
3170 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3171 if(PCW(pc)->pci.label)
3172 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3174 if(PCW(pc)->operand) {
3175 fprintf(of,";\toperand ");
3176 pCodeOpPrint(of,PCW(pc)->operand );
3182 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3183 if(PCFL(pc)->ancestor)
3184 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3191 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3195 fprintf(of,"unknown pCode type %d\n",pc->type);
3200 /*-----------------------------------------------------------------*/
3201 /* pCodePrintFunction - prints function begin/end */
3202 /*-----------------------------------------------------------------*/
3204 static void pCodePrintFunction(FILE *of, pCode *pc)
3210 if( ((pCodeFunction *)pc)->modname)
3211 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3213 if(PCF(pc)->fname) {
3214 pBranch *exits = PCF(pc)->to;
3216 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3219 exits = exits->next;
3222 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3225 if((PCF(pc)->from &&
3226 PCF(pc)->from->pc->type == PC_FUNCTION &&
3227 PCF(PCF(pc)->from->pc)->fname) )
3228 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3230 fprintf(of,"; exit point [can't find entry point]\n");
3233 /*-----------------------------------------------------------------*/
3234 /* pCodePrintLabel - prints label */
3235 /*-----------------------------------------------------------------*/
3237 static void pCodePrintLabel(FILE *of, pCode *pc)
3244 fprintf(of,"%s\n",PCL(pc)->label);
3245 else if (PCL(pc)->key >=0)
3246 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3248 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3251 /*-----------------------------------------------------------------*/
3252 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3253 /* remove it if it is found. */
3254 /*-----------------------------------------------------------------*/
3255 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3262 if(pcl->type == PC_OPCODE)
3263 b = PCI(pcl)->label;
3265 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3270 //fprintf (stderr, "%s \n",__FUNCTION__);
3271 //pcl->print(stderr,pcl);
3272 //pc->print(stderr,pc);
3275 //fprintf (stderr, "found label\n");
3279 bprev->next = b->next; /* Not first pCode in chain */
3283 PCI(pcl)->label = b->next; /* First pCode in chain */
3286 return; /* A label can't occur more than once */
3294 /*-----------------------------------------------------------------*/
3295 /*-----------------------------------------------------------------*/
3296 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3315 /*-----------------------------------------------------------------*/
3316 /* pBranchLink - given two pcodes, this function will link them */
3317 /* together through their pBranches */
3318 /*-----------------------------------------------------------------*/
3319 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3323 // Declare a new branch object for the 'from' pCode.
3325 //_ALLOC(b,sizeof(pBranch));
3326 b = Safe_calloc(1,sizeof(pBranch));
3327 b->pc = PCODE(t); // The link to the 'to' pCode.
3330 f->to = pBranchAppend(f->to,b);
3332 // Now do the same for the 'to' pCode.
3334 //_ALLOC(b,sizeof(pBranch));
3335 b = Safe_calloc(1,sizeof(pBranch));
3339 t->from = pBranchAppend(t->from,b);
3344 /*-----------------------------------------------------------------*/
3345 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3347 /*-----------------------------------------------------------------*/
3348 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3361 /*-----------------------------------------------------------------*/
3362 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3363 /*-----------------------------------------------------------------*/
3364 static void pCodeUnlink(pCode *pc)
3369 if(!pc->prev || !pc->next) {
3370 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3374 /* first remove the pCode from the chain */
3375 pc->prev->next = pc->next;
3376 pc->next->prev = pc->prev;
3378 /* Now for the hard part... */
3380 /* Remove the branches */
3384 pc1 = pb1->pc; /* Get the pCode that branches to the
3385 * one we're unlinking */
3387 /* search for the link back to this pCode (the one we're
3389 if(pb2 = pBranchFind(pc1->to,pc)) {
3390 pb2->pc = pc->to->pc; // make the replacement
3392 /* if the pCode we're unlinking contains multiple 'to'
3393 * branches (e.g. this a skip instruction) then we need
3394 * to copy these extra branches to the chain. */
3396 pBranchAppend(pb2, pc->to->next);
3405 /*-----------------------------------------------------------------*/
3406 /*-----------------------------------------------------------------*/
3408 static void genericAnalyze(pCode *pc)
3418 // Go through the pCodes that are in pCode chain and link
3419 // them together through the pBranches. Note, the pCodes
3420 // are linked together as a contiguous stream like the
3421 // assembly source code lines. The linking here mimics this
3422 // except that comments are not linked in.
3424 pCode *npc = pc->next;
3426 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3427 pBranchLink(pc,npc);
3432 /* reached the end of the pcode chain without finding
3433 * an instruction we could link to. */
3437 fprintf(stderr,"analyze PC_FLOW\n");
3441 fprintf(stderr,";A bad pCode is being used\n");
3447 /*-----------------------------------------------------------------*/
3448 /*-----------------------------------------------------------------*/
3449 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3453 if(pc->type == PC_LABEL) {
3454 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3457 if(pc->type == PC_OPCODE) {
3458 pbr = PCI(pc)->label;
3460 if(pbr->pc->type == PC_LABEL) {
3461 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3471 /*-----------------------------------------------------------------*/
3472 /*-----------------------------------------------------------------*/
3473 int checkLabel(pCode *pc)
3477 if(pc && isPCI(pc)) {
3478 pbr = PCI(pc)->label;
3480 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3490 /*-----------------------------------------------------------------*/
3491 /* findLabelinpBlock - Search the pCode for a particular label */
3492 /*-----------------------------------------------------------------*/
3493 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3500 for(pc = pb->pcHead; pc; pc = pc->next)
3501 if(compareLabel(pc,pcop_label))
3507 /*-----------------------------------------------------------------*/
3508 /* findLabel - Search the pCode for a particular label */
3509 /*-----------------------------------------------------------------*/
3510 pCode * findLabel(pCodeOpLabel *pcop_label)
3518 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3519 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3523 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3527 /*-----------------------------------------------------------------*/
3528 /* findNextpCode - given a pCode, find the next of type 'pct' */
3529 /* in the linked list */
3530 /*-----------------------------------------------------------------*/
3531 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3544 /*-----------------------------------------------------------------*/
3545 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3546 /* in the linked list */
3547 /*-----------------------------------------------------------------*/
3548 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3560 /*-----------------------------------------------------------------*/
3561 /* findNextInstruction - given a pCode, find the next instruction */
3562 /* in the linked list */
3563 /*-----------------------------------------------------------------*/
3564 pCode * findNextInstruction(pCode *pci)
3569 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3573 fprintf(stderr,"findNextInstruction: ");
3574 printpCode(stderr, pc);
3579 //fprintf(stderr,"Couldn't find instruction\n");
3583 /*-----------------------------------------------------------------*/
3584 /* findNextInstruction - given a pCode, find the next instruction */
3585 /* in the linked list */
3586 /*-----------------------------------------------------------------*/
3587 pCode * findPrevInstruction(pCode *pci)
3589 return findPrevpCode(pci, PC_OPCODE);
3592 /*-----------------------------------------------------------------*/
3593 /* findFunctionEnd - given a pCode find the end of the function */
3594 /* that contains it */
3595 /*-----------------------------------------------------------------*/
3596 pCode * findFunctionEnd(pCode *pc)
3600 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3606 fprintf(stderr,"Couldn't find function end\n");
3611 /*-----------------------------------------------------------------*/
3612 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3613 /* instruction with which it is associated. */
3614 /*-----------------------------------------------------------------*/
3615 static void AnalyzeLabel(pCode *pc)
3624 static void AnalyzeGOTO(pCode *pc)
3627 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3631 static void AnalyzeSKIP(pCode *pc)
3634 pBranchLink(pc,findNextInstruction(pc->next));
3635 pBranchLink(pc,findNextInstruction(pc->next->next));
3639 static void AnalyzeRETURN(pCode *pc)
3642 // branch_link(pc,findFunctionEnd(pc->next));
3648 /*-----------------------------------------------------------------*/
3649 /*-----------------------------------------------------------------*/
3650 regs * getRegFromInstruction(pCode *pc)
3656 PCI(pc)->num_ops == 0 )
3659 switch(PCI(pc)->pcop->type) {
3662 return PCOR(PCI(pc)->pcop)->r;
3664 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3668 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3669 return PCOR(PCI(pc)->pcop)->r;
3672 if(PCOI(PCI(pc)->pcop)->r)
3673 return (PCOI(PCI(pc)->pcop)->r);
3675 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3676 return dirregWithName(PCI(pc)->pcop->name);
3677 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3680 return PCOR(PCI(pc)->pcop)->r;
3682 case PO_GPR_REGISTER:
3684 //fprintf(stderr, "getRegFromInstruction - dir\n");
3685 return PCOR(PCI(pc)->pcop)->r;
3687 //fprintf(stderr, "getRegFromInstruction - literal\n");
3691 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3692 //genericPrint(stderr, pc);
3700 /*-----------------------------------------------------------------*/
3701 /*-----------------------------------------------------------------*/
3703 void AnalyzepBlock(pBlock *pb)
3710 /* Find all of the registers used in this pBlock
3711 * by looking at each instruction and examining it's
3714 for(pc = pb->pcHead; pc; pc = pc->next) {
3716 /* Is this an instruction with operands? */
3717 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3719 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3720 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3722 /* Loop through all of the registers declared so far in
3723 this block and see if we find this one there */
3725 regs *r = setFirstItem(pb->tregisters);
3728 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3729 PCOR(PCI(pc)->pcop)->r = r;
3732 r = setNextItem(pb->tregisters);
3736 /* register wasn't found */
3737 //r = Safe_calloc(1, sizeof(regs));
3738 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3739 //addSet(&pb->tregisters, r);
3740 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3741 //PCOR(PCI(pc)->pcop)->r = r;
3742 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3744 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3747 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3748 if(PCOR(PCI(pc)->pcop)->r) {
3749 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3750 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3752 if(PCI(pc)->pcop->name)
3753 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3755 fprintf(stderr,"ERROR: NULL register\n");
3764 /*-----------------------------------------------------------------*/
3766 /*-----------------------------------------------------------------*/
3767 void InsertpFlow(pCode *pc, pCode **pflow)
3770 PCFL(*pflow)->end = pc;
3772 if(!pc || !pc->next)
3775 *pflow = newpCodeFlow();
3776 pCodeInsertAfter(pc, *pflow);
3779 /*-----------------------------------------------------------------*/
3780 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3781 /* the flow blocks. */
3783 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3784 * point the instruction flow changes.
3786 /*-----------------------------------------------------------------*/
3787 void BuildFlow(pBlock *pb)
3790 pCode *last_pci=NULL;
3797 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3798 /* Insert a pCodeFlow object at the beginning of a pBlock */
3800 InsertpFlow(pb->pcHead, &pflow);
3802 //pflow = newpCodeFlow(); /* Create a new Flow object */
3803 //pflow->next = pb->pcHead; /* Make the current head the next object */
3804 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3805 //pb->pcHead = pflow; /* Make the Flow object the head */
3808 for( pc = findNextInstruction(pb->pcHead);
3810 pc=findNextInstruction(pc)) {
3813 PCI(pc)->pcflow = PCFL(pflow);
3815 //fprintf(stderr," build: ");
3816 //pflow->print(stderr,pflow);
3818 if( PCI(pc)->isSkip) {
3820 /* The two instructions immediately following this one
3821 * mark the beginning of a new flow segment */
3823 while(pc && PCI(pc)->isSkip) {
3825 PCI(pc)->pcflow = PCFL(pflow);
3829 InsertpFlow(pc, &pflow);
3830 pc=findNextInstruction(pc->next);
3838 PCI(pc)->pcflow = PCFL(pflow);
3840 InsertpFlow(pc, &pflow);
3842 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3844 InsertpFlow(pc, &pflow);
3847 } else if (checkLabel(pc)) {
3849 /* This instruction marks the beginning of a
3850 * new flow segment */
3855 /* If the previous pCode is not a flow object, then
3856 * insert a new flow object. (This check prevents
3857 * two consecutive flow objects from being insert in
3858 * the case where a skip instruction preceeds an
3859 * instruction containing a label.) */
3861 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3862 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3864 PCI(pc)->pcflow = PCFL(pflow);
3871 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3873 PCFL(pflow)->end = pb->pcTail;
3876 /*-------------------------------------------------------------------*/
3877 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3878 /* the flow blocks. */
3880 * unBuildFlow removes pCodeFlow objects from a pCode chain
3882 /*-----------------------------------------------------------------*/
3883 void unBuildFlow(pBlock *pb)
3898 if(PCI(pc)->pcflow) {
3899 //free(PCI(pc)->pcflow);
3900 PCI(pc)->pcflow = NULL;
3903 } else if(isPCFL(pc) )
3912 /*-----------------------------------------------------------------*/
3913 /*-----------------------------------------------------------------*/
3914 void dumpCond(int cond)
3917 static char *pcc_str[] = {
3931 int ncond = sizeof(pcc_str) / sizeof(char *);
3934 fprintf(stderr, "0x%04X\n",cond);
3936 for(i=0,j=1; i<ncond; i++, j<<=1)
3938 fprintf(stderr, " %s\n",pcc_str[i]);
3942 /*-----------------------------------------------------------------*/
3943 /*-----------------------------------------------------------------*/
3944 void FlowStats(pCodeFlow *pcflow)
3952 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3954 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3957 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3962 fprintf(stderr, " FlowStats inCond: ");
3963 dumpCond(pcflow->inCond);
3964 fprintf(stderr, " FlowStats outCond: ");
3965 dumpCond(pcflow->outCond);
3969 /*-----------------------------------------------------------------*
3970 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3971 * if it affects the banking bits.
3973 * return: -1 == Banking bits are unaffected by this pCode.
3975 * return: > 0 == Banking bits are affected.
3977 * If the banking bits are affected, then the returned value describes
3978 * which bits are affected and how they're affected. The lower half
3979 * of the integer maps to the bits that are affected, the upper half
3980 * to whether they're set or cleared.
3982 *-----------------------------------------------------------------*/
3984 #define SET_BANK_BIT (1 << 16)
3985 #define CLR_BANK_BIT 0
3987 static int isBankInstruction(pCode *pc)
3995 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3997 // Check to see if the register banks are changing
3998 if(PCI(pc)->isModReg) {
4000 pCodeOp *pcop = PCI(pc)->pcop;
4001 switch(PCI(pc)->op) {
4004 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4005 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4006 return SET_BANK_BIT | PIC_RP0_BIT;
4009 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4010 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4011 return CLR_BANK_BIT | PIC_RP0_BIT;
4016 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4017 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4018 return CLR_BANK_BIT | PIC_RP1_BIT;
4020 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4021 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4022 return CLR_BANK_BIT | PIC_RP1_BIT;
4026 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4027 //genericPrint(stderr, pc);
4038 /*-----------------------------------------------------------------*/
4039 /*-----------------------------------------------------------------*/
4041 static void FillFlow(pCodeFlow *pcflow)
4049 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4051 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4054 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4061 isBankInstruction(pc);
4063 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4066 fprintf(stderr, " FillFlow - Bad end of flow\n");
4068 fprintf(stderr, " FillFlow - Ending flow with\n ");
4069 pc->print(stderr,pc);
4072 fprintf(stderr, " FillFlow inCond: ");
4073 dumpCond(pcflow->inCond);
4074 fprintf(stderr, " FillFlow outCond: ");
4075 dumpCond(pcflow->outCond);
4080 /*-----------------------------------------------------------------*/
4081 /*-----------------------------------------------------------------*/
4082 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4084 pCodeFlowLink *fromLink, *toLink;
4086 if(!from || !to || !to->pcflow || !from->pcflow)
4089 fromLink = newpCodeFlowLink(from->pcflow);
4090 toLink = newpCodeFlowLink(to->pcflow);
4092 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4093 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4097 /*-----------------------------------------------------------------*
4098 * void LinkFlow(pBlock *pb)
4100 * In BuildFlow, the PIC code has been partitioned into contiguous
4101 * non-branching segments. In LinkFlow, we determine the execution
4102 * order of these segments. For example, if one of the segments ends
4103 * with a skip, then we know that there are two possible flow segments
4104 * to which control may be passed.
4105 *-----------------------------------------------------------------*/
4106 void LinkFlow(pBlock *pb)
4112 //fprintf(stderr,"linkflow \n");
4114 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4116 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4119 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4121 //fprintf(stderr," link: ");
4122 //pcflow->print(stderr,pcflow);
4124 //FillFlow(PCFL(pcflow));
4126 pc = PCFL(pcflow)->end;
4128 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4129 if(isPCI_SKIP(pc)) {
4130 //fprintf(stderr, "ends with skip\n");
4131 //pc->print(stderr,pc);
4132 pct=findNextInstruction(pc->next);
4133 LinkFlow_pCode(PCI(pc),PCI(pct));
4134 pct=findNextInstruction(pct->next);
4135 LinkFlow_pCode(PCI(pc),PCI(pct));
4139 if(isPCI_BRANCH(pc)) {
4140 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4142 //fprintf(stderr, "ends with branch\n ");
4143 //pc->print(stderr,pc);
4145 if(!(pcol && isPCOLAB(pcol))) {
4146 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4147 pc->print(stderr,pc);
4148 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4153 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4154 LinkFlow_pCode(PCI(pc),PCI(pct));
4156 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4157 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4158 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4164 //fprintf(stderr, "ends with non-branching instruction:\n");
4165 //pc->print(stderr,pc);
4167 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4173 //fprintf(stderr, "ends with unknown\n");
4174 //pc->print(stderr,pc);
4178 //fprintf(stderr, "ends with nothing: ERROR\n");
4182 /*-----------------------------------------------------------------*/
4183 /*-----------------------------------------------------------------*/
4185 /*-----------------------------------------------------------------*/
4186 /*-----------------------------------------------------------------*/
4187 int isPCinFlow(pCode *pc, pCode *pcflow)
4193 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4196 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4202 /*-----------------------------------------------------------------*/
4203 /*-----------------------------------------------------------------*/
4205 static void BanksUsedFlow2(pCode *pcflow)
4214 if(!isPCFL(pcflow)) {
4215 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4219 pc = findNextInstruction(pcflow->next);
4221 PCFL(pcflow)->lastBank = -1;
4223 while(isPCinFlow(pc,pcflow)) {
4225 int bank_selected = isBankInstruction(pc);
4227 //if(PCI(pc)->pcflow)
4228 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4230 if(bank_selected > 0) {
4231 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4233 // This instruction is modifying banking bits before accessing registers
4235 PCFL(pcflow)->firstBank = -1;
4237 if(PCFL(pcflow)->lastBank == -1)
4238 PCFL(pcflow)->lastBank = 0;
4240 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4241 if(bank_selected & SET_BANK_BIT)
4242 PCFL(pcflow)->lastBank |= bank;
4246 reg = getRegFromInstruction(pc);
4248 if(reg && !isREGinBank(reg, bank)) {
4249 int allbanks = REGallBanks(reg);
4251 PCFL(pcflow)->firstBank = allbanks;
4253 PCFL(pcflow)->lastBank = allbanks;
4260 pc = findNextInstruction(pc->next);
4263 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4264 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4267 /*-----------------------------------------------------------------*/
4268 /*-----------------------------------------------------------------*/
4270 static void BanksUsedFlow(pBlock *pb)
4275 //pb->pcHead->print(stderr, pb->pcHead);
4277 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4278 //pcflow->print(stderr,pcflow);
4280 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4282 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4284 BanksUsedFlow2(pcflow);
4290 /*-----------------------------------------------------------------*/
4291 /*-----------------------------------------------------------------*/
4292 static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci)
4295 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4297 /* Move the label, if there is one */
4300 new_pci->label = pci->label;
4304 /* Move the C code comment, if there is one */
4307 new_pci->cline = pci->cline;
4311 /* The new instruction has the same pcflow block */
4312 new_pci->pcflow = pci->pcflow;
4316 /*-----------------------------------------------------------------*/
4317 /*-----------------------------------------------------------------*/
4318 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4322 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4324 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4327 /*-----------------------------------------------------------------*/
4328 /*-----------------------------------------------------------------*/
4329 static void insertBankSel(pCodeInstruction *pci, const char *name)
4333 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4334 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4335 if (pcop->name == 0)
4336 pcop->name = strdup(name);
4337 new_pc = newpCode(POC_BANKSEL, pcop);
4339 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4342 /*-----------------------------------------------------------------*/
4343 /* If the register is a fixed known addess then we can assign the */
4344 /* bank selection bits. Otherwise the linker is going to assign */
4345 /* the register location and thus has to set bank selection bits */
4346 /* through the banksel directive. */
4347 /* One critical assumption here is that within this C module all */
4348 /* the locally allocated registers are in the same udata sector. */
4349 /* Therefore banksel is only called for external registers or the */
4350 /* first time a local register is encountered. */
4351 /*-----------------------------------------------------------------*/
4352 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4353 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4356 int a = reg->alias>>7;
4358 return cur_bank; // This register is available in all banks
4359 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4360 return cur_bank; // This register is available in banks 0 & 1
4362 if (reg->address&0x80) {
4363 if ((cur_bank==1)||(cur_bank==3)) {
4364 return cur_bank; // This register is available in banks 1 & 3
4367 if ((cur_bank==0)||(cur_bank==1)) {
4368 return cur_bank; // This register is available in banks 0 & 2
4373 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4375 LastRegIdx = reg->rIdx;
4378 bank = REG_BANK(reg);
4379 } else if (reg->isExtern) {
4380 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4382 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4384 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.
4385 return 'L'; // Local registers are presumed to be in same linker assigned bank
4386 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4387 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4388 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4389 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4390 } 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
4391 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4392 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4393 } else { // Current bank and new register banks known - can set bank bits
4394 switch((cur_bank^bank) & 3) {
4398 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4401 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4404 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4405 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4413 /*-----------------------------------------------------------------*/
4414 /* Check for bank selection pcodes instructions and modify */
4415 /* cur_bank to match. */
4416 /*-----------------------------------------------------------------*/
4417 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4419 if (isSTATUS_REG(reg)) {
4421 if (PCI(pc)->op == POC_BCF) {
4422 int old_bank = *cur_bank;
4423 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4424 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4425 if (*cur_bank & ~(0x3))
4428 *cur_bank = *cur_bank&0x2;
4429 LastRegIdx = reg->rIdx;
4430 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4431 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4432 if (*cur_bank & ~(0x3))
4435 *cur_bank = *cur_bank&0x1;
4436 LastRegIdx = reg->rIdx;
4438 return old_bank != *cur_bank;
4441 if (PCI(pc)->op == POC_BSF) {
4442 int old_bank = *cur_bank;
4443 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4444 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4445 if (*cur_bank & ~(0x3))
4448 *cur_bank = (*cur_bank&0x2) | 0x1;
4449 LastRegIdx = reg->rIdx;
4450 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4451 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4452 if (*cur_bank & ~(0x3))
4455 *cur_bank = (*cur_bank&0x1) | 0x2;
4456 LastRegIdx = reg->rIdx;
4458 return old_bank != *cur_bank;
4461 } else if (PCI(pc)->op == POC_BANKSEL) {
4462 int old_bank = *cur_bank;
4463 *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L';
4464 LastRegIdx = reg->rIdx;
4465 return old_bank != *cur_bank;
4471 /*-----------------------------------------------------------------*/
4472 /* Set bank selection if necessary */
4473 /*-----------------------------------------------------------------*/
4474 static int DoBankSelect(pCode *pc, int cur_bank) {
4482 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4483 if (pcf && isPCF(pcf)) {
4485 int rbank = 'U'; // Undetermined
4486 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4487 // Check all the returns to work out what bank is selected
4488 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4490 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4492 rbank = PCFL(pcfr)->lastBank;
4494 if (rbank != PCFL(pcfr)->lastBank)
4495 return -1; // Unknown bank - multiple returns with different banks
4500 return -1; // Unknown bank
4502 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4503 /* Extern functions may use registers in different bank - must call banksel */
4504 return -1; /* Unknown bank */
4508 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4509 return -1; /* New bank unknown - linkers choice. */
4512 reg = getRegFromInstruction(pc);
4515 if (IsBankChange(pc,reg,&cur_bank))
4518 if (!isPCI_LIT(pc)) {
4520 /* Examine the instruction before this one to make sure it is
4521 * not a skip type instruction */
4522 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4524 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4525 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4527 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4529 if (!PCI(pc)->pcflow)
4530 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4532 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4538 /*-----------------------------------------------------------------*/
4539 /*-----------------------------------------------------------------*/
4541 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4549 pc = findNextInstruction(pcfl->pc.next);
4551 while(isPCinFlow(pc,PCODE(pcfl))) {
4553 cur_bank = DoBankSelect(pc,cur_bank);
4555 pc = findNextInstruction(pc->next);
4559 if(pcprev && cur_bank) {
4560 // Set bank state to unknown at the end of each flow block
4566 /*-----------------------------------------------------------------*/
4567 /*int compareBankFlow - compare the banking requirements between */
4569 /*-----------------------------------------------------------------*/
4571 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4574 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4577 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4580 if(pcflow->firstBank == -1)
4584 if(pcflowLink->pcflow->firstBank == -1) {
4585 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4586 pcflowLink->pcflow->to :
4587 pcflowLink->pcflow->from);
4588 return compareBankFlow(pcflow, pctl, toORfrom);
4592 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4595 pcflowLink->bank_conflict++;
4596 pcflowLink->pcflow->FromConflicts++;
4597 pcflow->ToConflicts++;
4600 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4603 pcflowLink->bank_conflict++;
4604 pcflowLink->pcflow->ToConflicts++;
4605 pcflow->FromConflicts++;
4609 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4610 pcflowLink->pcflow->pc.seq,
4611 pcflowLink->pcflow->FromConflicts,
4612 pcflowLink->pcflow->ToConflicts);
4618 /*-----------------------------------------------------------------*/
4619 /*-----------------------------------------------------------------*/
4621 void FixBankFlow(pBlock *pb)
4625 pCodeFlowLink *pcfl;
4627 pCode *pcflow_max_To=NULL;
4628 pCode *pcflow_max_From=NULL;
4629 int max_ToConflicts=0;
4630 int max_FromConflicts=0;
4632 //fprintf(stderr,"Fix Bank flow \n");
4633 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4637 First loop through all of the flow objects in this pcode block
4638 and fix the ones that have banking conflicts between the
4642 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4644 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4646 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4648 if(!isPCFL(pcflow)) {
4649 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4653 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4654 PCFL(pcflow)->firstBank >= 0 &&
4655 PCFL(pcflow)->lastBank >= 0 ) {
4657 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4658 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4660 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4661 BanksUsedFlow2(pcflow);
4666 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4668 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4670 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4675 if(!isPCFL(pcflow)) {
4676 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4680 PCFL(pcflow)->FromConflicts = 0;
4681 PCFL(pcflow)->ToConflicts = 0;
4686 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4687 pcfl = setFirstItem(PCFL(pcflow)->from);
4690 pc = PCODE(pcfl->pcflow);
4693 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4694 pc->print(stderr,pc);
4697 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4700 pcfl=setNextItem(PCFL(pcflow)->from);
4703 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4704 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4706 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4707 BanksUsedFlow2(pcflow);
4709 continue; / * Don't need to check the flow from here - it's already been fixed * /
4716 pcfl = setFirstItem(PCFL(pcflow)->to);
4719 pc = PCODE(pcfl->pcflow);
4721 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4722 pc->print(stderr,pc);
4725 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4728 pcfl=setNextItem(PCFL(pcflow)->to);
4731 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4732 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4734 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4735 BanksUsedFlow2(pcflow);
4740 Loop through the flow objects again and find the ones with the
4744 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4746 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4748 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4749 pcflow_max_To = pcflow;
4751 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4752 pcflow_max_From = pcflow;
4756 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4757 PCFL(pcflow_max_To)->pc.seq,
4758 PCFL(pcflow_max_To)->ToConflicts);
4761 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4762 PCFL(pcflow_max_From)->pc.seq,
4763 PCFL(pcflow_max_From)->FromConflicts);
4768 /*-----------------------------------------------------------------*/
4769 /*-----------------------------------------------------------------*/
4770 void DumpFlow(pBlock *pb)
4774 pCodeFlowLink *pcfl;
4777 fprintf(stderr,"Dump flow \n");
4778 pb->pcHead->print(stderr, pb->pcHead);
4780 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4781 pcflow->print(stderr,pcflow);
4783 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4785 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4787 if(!isPCFL(pcflow)) {
4788 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4791 fprintf(stderr,"dumping: ");
4792 pcflow->print(stderr,pcflow);
4793 FlowStats(PCFL(pcflow));
4795 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4797 pc = PCODE(pcfl->pcflow);
4799 fprintf(stderr, " from seq %d:\n",pc->seq);
4801 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4802 pc->print(stderr,pc);
4807 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4809 pc = PCODE(pcfl->pcflow);
4811 fprintf(stderr, " to seq %d:\n",pc->seq);
4813 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4814 pc->print(stderr,pc);
4823 /*-----------------------------------------------------------------*/
4824 /*-----------------------------------------------------------------*/
4825 int OptimizepBlock(pBlock *pb)
4830 if(!pb || !peepOptimizing)
4833 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4835 for(pc = pb->pcHead; pc; pc = pc->next)
4836 matches += pCodePeepMatchRule(pc);
4839 pc = findNextInstruction(pb->pcHead);
4847 if(pCodePeepMatchRule(pc)) {
4852 pc = findNextInstruction(pcprev->next);
4854 pc = findNextInstruction(pb->pcHead);
4856 pc = findNextInstruction(pc->next);
4860 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4865 /*-----------------------------------------------------------------*/
4866 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4867 /*-----------------------------------------------------------------*/
4868 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4872 for(pc = pcs; pc; pc = pc->next) {
4874 if((pc->type == PC_OPCODE) &&
4876 (PCI(pc)->pcop->type == PO_LABEL) &&
4877 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4885 /*-----------------------------------------------------------------*/
4886 /*-----------------------------------------------------------------*/
4887 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4894 (PCI(pc)->pcop->type == PO_LABEL)) {
4896 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4898 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4900 free(pcol->pcop.name);
4902 /* If the key is negative, then we (probably) have a label to
4903 * a function and the name is already defined */
4906 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4910 //sprintf(buffer,"_%05d_DS_",pcl->key);
4912 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4914 pcol->pcop.name = Safe_strdup(s);
4915 pcol->key = pcl->key;
4916 //pc->print(stderr,pc);
4923 /*-----------------------------------------------------------------*/
4924 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4925 /* pCode chain if they're not used. */
4926 /*-----------------------------------------------------------------*/
4927 void pBlockRemoveUnusedLabels(pBlock *pb)
4929 pCode *pc; pCodeLabel *pcl;
4934 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4936 pBranch *pbr = PCI(pc)->label;
4937 if(pbr && pbr->next) {
4938 pCode *pcd = pb->pcHead;
4940 //fprintf(stderr, "multiple labels\n");
4941 //pc->print(stderr,pc);
4946 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4947 //fprintf(stderr,"Used by:\n");
4948 //pcd->print(stderr,pcd);
4950 exchangeLabels(PCL(pbr->pc),pcd);
4959 for(pc = pb->pcHead; pc; pc = pc->next) {
4961 if(isPCL(pc)) // Label pcode
4963 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4964 pcl = PCL(PCI(pc)->label->pc);
4967 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4969 /* This pCode is a label, so search the pBlock to see if anyone
4972 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4973 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4974 /* Couldn't find an instruction that refers to this label
4975 * So, unlink the pCode label from it's pCode chain
4976 * and destroy the label */
4977 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4979 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4980 if(pc->type == PC_LABEL) {
4982 pCodeLabelDestruct(pc);
4984 unlinkpCodeFromBranch(pc, PCODE(pcl));
4985 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4996 /*-----------------------------------------------------------------*/
4997 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4998 /* chain and put them into pBranches that are */
4999 /* associated with the appropriate pCode */
5001 /*-----------------------------------------------------------------*/
5002 void pBlockMergeLabels(pBlock *pb)
5005 pCode *pc, *pcnext=NULL;
5010 /* First, Try to remove any unused labels */
5011 //pBlockRemoveUnusedLabels(pb);
5013 /* Now loop through the pBlock and merge the labels with the opcodes */
5016 // for(pc = pb->pcHead; pc; pc = pc->next) {
5019 pCode *pcn = pc->next;
5021 if(pc->type == PC_LABEL) {
5023 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5024 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5025 if((pcnext = findNextInstruction(pc) )) {
5027 // Unlink the pCode label from it's pCode chain
5030 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5031 // And link it into the instruction's pBranch labels. (Note, since
5032 // it's possible to have multiple labels associated with one instruction
5033 // we must provide a means to accomodate the additional labels. Thus
5034 // the labels are placed into the singly-linked list "label" as
5035 // opposed to being a single member of the pCodeInstruction.)
5037 //_ALLOC(pbr,sizeof(pBranch));
5038 pbr = Safe_calloc(1,sizeof(pBranch));
5042 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5045 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5047 } else if(pc->type == PC_CSOURCE) {
5049 /* merge the source line symbolic info into the next instruction */
5050 if((pcnext = findNextInstruction(pc) )) {
5052 // Unlink the pCode label from it's pCode chain
5054 PCI(pcnext)->cline = PCCS(pc);
5055 //fprintf(stderr, "merging CSRC\n");
5056 //genericPrint(stderr,pcnext);
5062 pBlockRemoveUnusedLabels(pb);
5066 /*-----------------------------------------------------------------*/
5067 /*-----------------------------------------------------------------*/
5068 int OptimizepCode(char dbName)
5070 #define MAX_PASSES 4
5079 DFPRINTF((stderr," Optimizing pCode\n"));
5083 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5084 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5085 matches += OptimizepBlock(pb);
5088 while(matches && ++passes < MAX_PASSES);
5093 /*-----------------------------------------------------------------*/
5094 /* popCopyGPR2Bit - copy a pcode operator */
5095 /*-----------------------------------------------------------------*/
5097 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5101 pcop = newpCodeOpBit(pc->name, bitval, 0);
5103 if( !( (pcop->type == PO_LABEL) ||
5104 (pcop->type == PO_LITERAL) ||
5105 (pcop->type == PO_STR) ))
5106 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5112 /*-----------------------------------------------------------------*/
5113 /*-----------------------------------------------------------------*/
5114 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5117 int firstBank = 'U';
5122 for (pc=pb->pcHead; pc; pc=pc->next) {
5124 firstBank = PCFL(pc)->firstBank;
5128 if (firstBank != 'U') {
5129 /* This block has already been done */
5130 if (firstBank != cur_bank) {
5131 /* This block has started with a different bank - must adjust it */
5132 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5135 regs *reg = getRegFromInstruction(pc);
5137 DoBankSelect(pc,cur_bank);
5147 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5150 for (pc=pb->pcHead; pc; pc=pc->next) {
5152 PCFL(pc)->firstBank = cur_bank;
5155 cur_bank = DoBankSelect(pc,cur_bank);
5158 /* Trace through branches and set the bank selection as required. */
5161 for (pc=pb->pcHead; pc; pc=pc->next) {
5163 PCFL(pc)->firstBank = cur_bank;
5167 if (PCI(pc)->op == POC_GOTO) {
5168 int lastRegIdx = LastRegIdx;
5170 /* Trace through branch */
5171 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5174 regs *reg = getRegFromInstruction(pcl);
5176 int bankUnknown = -1;
5177 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5179 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5185 LastRegIdx = lastRegIdx;
5187 /* Keep track out current bank */
5188 regs *reg = getRegFromInstruction(pc);
5190 IsBankChange(pc,reg,&cur_bank);
5197 /*-----------------------------------------------------------------*/
5198 /*-----------------------------------------------------------------*/
5199 void pBlockDestruct(pBlock *pb)
5210 /*-----------------------------------------------------------------*/
5211 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5212 /* name dbName and combine them */
5213 /* into one block */
5214 /*-----------------------------------------------------------------*/
5215 void mergepBlocks(char dbName)
5218 pBlock *pb, *pbmerged = NULL,*pbn;
5220 pb = the_pFile->pbHead;
5222 //fprintf(stderr," merging blocks named %c\n",dbName);
5226 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5227 if( getpBlock_dbName(pb) == dbName) {
5229 //fprintf(stderr," merged block %c\n",dbName);
5234 addpCode2pBlock(pbmerged, pb->pcHead);
5235 /* addpCode2pBlock doesn't handle the tail: */
5236 pbmerged->pcTail = pb->pcTail;
5238 pb->prev->next = pbn;
5240 pbn->prev = pb->prev;
5245 //printpBlock(stderr, pbmerged);
5252 /*-----------------------------------------------------------------*/
5253 /* AnalyzeFlow - Examine the flow of the code and optimize */
5255 /* level 0 == minimal optimization */
5256 /* optimize registers that are used only by two instructions */
5257 /* level 1 == maximal optimization */
5258 /* optimize by looking at pairs of instructions that use the */
5260 /*-----------------------------------------------------------------*/
5262 void AnalyzeFlow(int level)
5264 static int times_called=0;
5272 /* if this is not the first time this function has been called,
5273 then clean up old flow information */
5274 if(times_called++) {
5275 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5278 RegsUnMapLiveRanges();
5284 /* Phase 2 - Flow Analysis - Register Banking
5286 * In this phase, the individual flow blocks are examined
5287 * and register banking is fixed.
5290 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5291 //FixRegisterBanking(pb);
5293 /* Phase 2 - Flow Analysis
5295 * In this phase, the pCode is partition into pCodeFlow
5296 * blocks. The flow blocks mark the points where a continuous
5297 * stream of instructions changes flow (e.g. because of
5298 * a call or goto or whatever).
5301 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5305 /* Phase 2 - Flow Analysis - linking flow blocks
5307 * In this phase, the individual flow blocks are examined
5308 * to determine their order of excution.
5311 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5314 /* Phase 3 - Flow Analysis - Flow Tree
5316 * In this phase, the individual flow blocks are examined
5317 * to determine their order of excution.
5320 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5324 /* Phase x - Flow Analysis - Used Banks
5326 * In this phase, the individual flow blocks are examined
5327 * to determine the Register Banks they use
5330 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5334 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5335 pCodeRegMapLiveRanges(pb);
5337 RemoveUnusedRegisters();
5339 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5340 pCodeRegOptimizeRegUsage(level);
5346 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5351 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5353 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5354 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5355 pcflow = pcflow->next) {
5357 FillFlow(PCFL(pcflow));
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 FlowStats(PCFL(pcflow));
5374 /*-----------------------------------------------------------------*/
5375 /* AnalyzeBanking - Called after the memory addresses have been */
5376 /* assigned to the registers. */
5378 /*-----------------------------------------------------------------*/
5380 void AnalyzeBanking(void)
5384 if(!picIsInitialized()) {
5385 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5386 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5387 fprintf(stderr,"support/scripts/inc2h.pl\n");
5388 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5393 /* Phase x - Flow Analysis - Used Banks
5395 * In this phase, the individual flow blocks are examined
5396 * to determine the Register Banks they use
5402 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5403 // BanksUsedFlow(pb);
5404 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5405 FixRegisterBanking(pb,-1); // cur_bank is unknown
5409 /*-----------------------------------------------------------------*/
5410 /*-----------------------------------------------------------------*/
5411 DEFSETFUNC (resetrIdx)
5413 if (!((regs *)item)->isFixed)
5414 ((regs *)item)->rIdx = 0;
5419 /*-----------------------------------------------------------------*/
5420 /* InitRegReuse - Initialises variables for code analyzer */
5421 /*-----------------------------------------------------------------*/
5423 void InitReuseReg(void)
5425 /* Find end of statically allocated variables for start idx */
5426 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5428 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5429 if (r->type != REG_SFR) {
5430 maxIdx += r->size; /* Increment for all statically allocated variables */
5434 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5437 /*-----------------------------------------------------------------*/
5438 /*-----------------------------------------------------------------*/
5439 static unsigned register_reassign(pBlock *pb, unsigned idx)
5443 /* check recursion */
5444 pc = setFirstItem(pb->function_entries);
5450 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5452 if (pb->tregisters) {
5454 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5455 if (r->type == REG_GPR) {
5457 if (r->rIdx < (int)idx) {
5460 if (peakIdx < idx) peakIdx = idx;
5461 sprintf(s,"r0x%02X", r->rIdx);
5462 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5464 r->name = Safe_strdup(s);
5470 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5472 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5473 char *dest = get_op_from_instruction(PCI(pc));
5475 pCode *pcn = findFunction(dest);
5477 register_reassign(pcn->pb,idx);
5486 /*------------------------------------------------------------------*/
5487 /* ReuseReg were call tree permits */
5489 /* Re-allocate the GPR for optimum reuse for a given pblock */
5490 /* eg if a function m() calls function f1() and f2(), where f1 */
5491 /* allocates a local variable vf1 and f2 allocates a local */
5492 /* variable vf2. Then providing f1 and f2 do not call each other */
5493 /* they may share the same general purpose registers for vf1 and */
5495 /* This is done by first setting the the regs rIdx to start after */
5496 /* all the global variables, then walking through the call tree */
5497 /* renaming the registers to match their new idx and incrementng */
5498 /* it as it goes. If a function has already been called it will */
5499 /* only rename the registers if it has already used up those */
5500 /* registers ie rIdx of the function's registers is lower than the */
5501 /* current rIdx. That way the register will not be reused while */
5502 /* still being used by an eariler function call. */
5504 /* Note for this to work the fucntions need to be declared static. */
5506 /*------------------------------------------------------------------*/
5511 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5512 /* Non static functions can be called from other modules so their registers must reassign */
5513 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5514 register_reassign(pb,peakIdx);
5518 /*-----------------------------------------------------------------*/
5519 /* buildCallTree - look at the flow and extract all of the calls */
5521 /*-----------------------------------------------------------------*/
5523 void buildCallTree(void )
5532 /* Now build the call tree.
5533 First we examine all of the pCodes for functions.
5534 Keep in mind that the function boundaries coincide
5535 with pBlock boundaries.
5537 The algorithm goes something like this:
5538 We have two nested loops. The outer loop iterates
5539 through all of the pBlocks/functions. The inner
5540 loop iterates through all of the pCodes for
5541 a given pBlock. When we begin iterating through
5542 a pBlock, the variable pc_fstart, pCode of the start
5543 of a function, is cleared. We then search for pCodes
5544 of type PC_FUNCTION. When one is encountered, we
5545 initialize pc_fstart to this and at the same time
5546 associate a new pBranch object that signifies a
5547 branch entry. If a return is found, then this signifies
5548 a function exit point. We'll link the pCodes of these
5549 returns to the matching pc_fstart.
5551 When we're done, a doubly linked list of pBranches
5552 will exist. The head of this list is stored in
5553 `the_pFile', which is the meta structure for all
5554 of the pCode. Look at the printCallTree function
5555 on how the pBranches are linked together.
5558 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5559 pCode *pc_fstart=NULL;
5560 for(pc = pb->pcHead; pc; pc = pc->next) {
5562 pCodeFunction *pcf = PCF(pc);
5565 if(STRCASECMP(pcf->fname, "_main") == 0) {
5566 //fprintf(stderr," found main \n");
5567 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5571 pbr = Safe_calloc(1,sizeof(pBranch));
5572 pbr->pc = pc_fstart = pc;
5575 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5577 // Here's a better way of doing the same:
5578 addSet(&pb->function_entries, pc);
5581 // Found an exit point in a function, e.g. return
5582 // (Note, there may be more than one return per function)
5584 pBranchLink(PCF(pc_fstart), pcf);
5586 addSet(&pb->function_exits, pc);
5588 } else if(isCALL(pc)) {
5589 addSet(&pb->function_calls,pc);
5595 /*-----------------------------------------------------------------*/
5596 /* AnalyzepCode - parse the pCode that has been generated and form */
5597 /* all of the logical connections. */
5599 /* Essentially what's done here is that the pCode flow is */
5601 /*-----------------------------------------------------------------*/
5603 void AnalyzepCode(char dbName)
5614 /* Phase 1 - Register allocation and peep hole optimization
5616 * The first part of the analysis is to determine the registers
5617 * that are used in the pCode. Once that is done, the peep rules
5618 * are applied to the code. We continue to loop until no more
5619 * peep rule optimizations are found (or until we exceed the
5620 * MAX_PASSES threshold).
5622 * When done, the required registers will be determined.
5628 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5630 /* First, merge the labels with the instructions */
5631 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5632 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5634 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5635 pBlockMergeLabels(pb);
5638 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5642 changes = OptimizepCode(dbName);
5644 } while(changes && (i++ < MAX_PASSES));
5649 /*-----------------------------------------------------------------*/
5650 /* ispCodeFunction - returns true if *pc is the pCode of a */
5652 /*-----------------------------------------------------------------*/
5653 bool ispCodeFunction(pCode *pc)
5656 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5662 /*-----------------------------------------------------------------*/
5663 /* findFunction - Search for a function by name (given the name) */
5664 /* in the set of all functions that are in a pBlock */
5665 /* (note - I expect this to change because I'm planning to limit */
5666 /* pBlock's to just one function declaration */
5667 /*-----------------------------------------------------------------*/
5668 pCode *findFunction(char *fname)
5675 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5677 pc = setFirstItem(pb->function_entries);
5680 if((pc->type == PC_FUNCTION) &&
5682 (strcmp(fname, PCF(pc)->fname)==0))
5685 pc = setNextItem(pb->function_entries);
5693 void MarkUsedRegisters(set *regset)
5698 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5699 r2 = pic14_regWithIdx(r1->rIdx);
5707 void pBlockStats(FILE *of, pBlock *pb)
5713 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5715 // for now just print the first element of each set
5716 pc = setFirstItem(pb->function_entries);
5718 fprintf(of,";entry: ");
5721 pc = setFirstItem(pb->function_exits);
5723 fprintf(of,";has an exit\n");
5727 pc = setFirstItem(pb->function_calls);
5729 fprintf(of,";functions called:\n");
5732 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5733 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5735 pc = setNextItem(pb->function_calls);
5739 r = setFirstItem(pb->tregisters);
5741 int n = elementsInSet(pb->tregisters);
5743 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5746 fprintf(of,"; %s\n",r->name);
5747 r = setNextItem(pb->tregisters);
5752 /*-----------------------------------------------------------------*/
5753 /*-----------------------------------------------------------------*/
5755 static void sequencepCode(void)
5761 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5763 pb->seq = GpCodeSequenceNumber+1;
5765 for( pc = pb->pcHead; pc; pc = pc->next)
5766 pc->seq = ++GpCodeSequenceNumber;
5772 /*-----------------------------------------------------------------*/
5773 /*-----------------------------------------------------------------*/
5775 set *register_usage(pBlock *pb)
5778 set *registers=NULL;
5779 set *registersInCallPath = NULL;
5781 / * check recursion * /
5783 pc = setFirstItem(pb->function_entries);
5790 if(pc->type != PC_FUNCTION)
5791 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5793 pc = setFirstItem(pb->function_calls);
5794 for( ; pc; pc = setNextItem(pb->function_calls)) {
5796 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5797 char *dest = get_op_from_instruction(PCI(pc));
5799 pcn = findFunction(dest);
5801 registersInCallPath = register_usage(pcn->pb);
5803 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5808 pBlockStats(stderr,pb); // debug
5811 // Mark the registers in this block as used.
5813 MarkUsedRegisters(pb->tregisters);
5814 if(registersInCallPath) {
5815 / * registers were used in the functions this pBlock has called * /
5816 / * so now, we need to see if these collide with the ones we are * /
5819 regs *r1,*r2, *newreg;
5821 DFPRINTF((stderr,"comparing registers\n"));
5823 r1 = setFirstItem(registersInCallPath);
5825 if (r1->type != REG_STK) {
5826 r2 = setFirstItem(pb->tregisters);
5828 while(r2 && (r2->type != REG_STK)) {
5830 if(r2->rIdx == r1->rIdx) {
5831 newreg = pic14_findFreeReg(REG_GPR);
5835 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5839 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5840 r1->rIdx, newreg->rIdx));
5841 r2->rIdx = newreg->rIdx;
5843 r2->name = Safe_strdup(newreg->name);
5847 newreg->wasUsed = 1;
5849 r2 = setNextItem(pb->tregisters);
5853 r1 = setNextItem(registersInCallPath);
5856 / * Collisions have been resolved. Now free the registers in the call path * /
5857 r1 = setFirstItem(registersInCallPath);
5859 newreg = pic14_regWithIdx(r1->rIdx);
5860 if (newreg) newreg->isFree = 1;
5861 r1 = setNextItem(registersInCallPath);
5865 // MarkUsedRegisters(pb->registers);
5867 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5870 DFPRINTF((stderr,"returning regs\n"));
5872 DFPRINTF((stderr,"not returning regs\n"));
5874 DFPRINTF((stderr,"pBlock after register optim.\n"));
5875 pBlockStats(stderr,pb); // debug
5882 /*-----------------------------------------------------------------*/
5883 /* printCallTree - writes the call tree to a file */
5885 /*-----------------------------------------------------------------*/
5886 void pct2(FILE *of,pBlock *pb,int indent)
5890 // set *registersInCallPath = NULL;
5896 return; //recursion ?
5898 pc = setFirstItem(pb->function_entries);
5905 for(i=0;i<indent;i++) // Indentation
5908 if(pc->type == PC_FUNCTION)
5909 fprintf(of,"%s\n",PCF(pc)->fname);
5914 pc = setFirstItem(pb->function_calls);
5915 for( ; pc; pc = setNextItem(pb->function_calls)) {
5917 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5918 char *dest = get_op_from_instruction(PCI(pc));
5920 pcn = findFunction(dest);
5922 pct2(of,pcn->pb,indent+1);
5924 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5932 /*-----------------------------------------------------------------*/
5933 /* printCallTree - writes the call tree to a file */
5935 /*-----------------------------------------------------------------*/
5937 void printCallTree(FILE *of)
5949 fprintf(of, "\npBlock statistics\n");
5950 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5955 fprintf(of,"Call Tree\n");
5956 pbr = the_pFile->functions;
5960 if(!ispCodeFunction(pc))
5961 fprintf(of,"bug in call tree");
5964 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5966 while(pc->next && !ispCodeFunction(pc->next)) {
5968 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5969 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5977 fprintf(of,"\n**************\n\na better call tree\n");
5978 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5983 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5984 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5990 /*-----------------------------------------------------------------*/
5992 /*-----------------------------------------------------------------*/
5994 void InlineFunction(pBlock *pb)
6002 pc = setFirstItem(pb->function_calls);
6004 for( ; pc; pc = setNextItem(pb->function_calls)) {
6007 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6008 pCode *pcp = pc->prev;
6014 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 */
6016 InlineFunction(pcn->pb);
6019 At this point, *pc points to a CALL mnemonic, and
6020 *pcn points to the function that is being called.
6022 To in-line this call, we need to remove the CALL
6023 and RETURN(s), and link the function pCode in with
6030 /* Check if previous instruction was a bit skip */
6031 if (isPCI_BITSKIP(pcp)) {
6033 /* Invert skip instruction and add a goto */
6034 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6036 if(isPCL(pc_call->next)) { // Label pcode
6037 pcl = PCL(pc_call->next);
6038 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6039 pcl = PCL(PCI(pc_call->next)->label->pc);
6041 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6042 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6044 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6047 /* remove callee pBlock from the pBlock linked list */
6048 removepBlock(pcn->pb);
6056 /* Remove the Function pCode */
6057 pct = findNextInstruction(pcn->next);
6059 /* Link the function with the callee */
6060 if (pcp) pcp->next = pcn->next;
6061 pcn->next->prev = pcp;
6063 /* Convert the function name into a label */
6065 pbr = Safe_calloc(1,sizeof(pBranch));
6066 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6068 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6069 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6071 /* turn all of the return's except the last into goto's */
6072 /* check case for 2 instruction pBlocks */
6073 pce = findNextInstruction(pcn->next);
6075 pCode *pce_next = findNextInstruction(pce->next);
6077 if(pce_next == NULL) {
6078 /* found the last return */
6079 pCode *pc_call_next = findNextInstruction(pc_call->next);
6081 //fprintf(stderr,"found last return\n");
6082 //pce->print(stderr,pce);
6083 pce->prev->next = pc_call->next;
6084 pc_call->next->prev = pce->prev;
6085 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6094 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6100 /*-----------------------------------------------------------------*/
6102 /*-----------------------------------------------------------------*/
6104 void InlinepCode(void)
6113 if(!functionInlining)
6116 /* Loop through all of the function definitions and count the
6117 * number of times each one is called */
6118 //fprintf(stderr,"inlining %d\n",__LINE__);
6120 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6122 pc = setFirstItem(pb->function_calls);
6124 for( ; pc; pc = setNextItem(pb->function_calls)) {
6127 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6128 if(pcn && isPCF(pcn)) {
6129 PCF(pcn)->ncalled++;
6132 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6137 //fprintf(stderr,"inlining %d\n",__LINE__);
6139 /* Now, Loop through the function definitions again, but this
6140 * time inline those functions that have only been called once. */
6142 InlineFunction(the_pFile->pbHead);
6143 //fprintf(stderr,"inlining %d\n",__LINE__);
6145 for(pb = the_pFile->pbHead; pb; pb = pb->next)