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)
1598 pb = the_pFile->pbHead;
1602 if(getpBlock_dbName(pb) == dbName) {
1603 pBlock *pbn = pb->next;
1604 pb->next = the_pFile->pbHead;
1605 the_pFile->pbHead->prev = pb;
1606 the_pFile->pbHead = pb;
1609 pb->prev->next = pbn;
1611 // If the pBlock that we just moved was the last
1612 // one in the link of all of the pBlocks, then we
1613 // need to point the tail to the block just before
1614 // the one we moved.
1615 // Note: if pb->next is NULL, then pb must have
1616 // been the last pBlock in the chain.
1619 pbn->prev = pb->prev;
1621 the_pFile->pbTail = pb->prev;
1632 void copypCode(FILE *of, char dbName)
1636 if(!of || !the_pFile)
1639 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1640 if(getpBlock_dbName(pb) == dbName) {
1648 void pcode_test(void)
1651 DFPRINTF((stderr,"pcode is alive!\n"));
1661 /* create the file name */
1662 strcpy(buffer,dstFileName);
1663 strcat(buffer,".p");
1665 if( !(pFile = fopen(buffer, "w" ))) {
1666 werror(E_FILE_OPEN_ERR,buffer);
1670 fprintf(pFile,"pcode dump\n\n");
1672 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1673 fprintf(pFile,"\n\tNew pBlock\n\n");
1675 fprintf(pFile,"%s",pb->cmemmap->sname);
1677 fprintf(pFile,"internal pblock");
1679 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1680 printpBlock(pFile,pb);
1684 /*-----------------------------------------------------------------*/
1685 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1686 /* ister, RegCond will return the bit being referenced. */
1688 /* fixme - why not just OR in the pcop bit field */
1689 /*-----------------------------------------------------------------*/
1691 static int RegCond(pCodeOp *pcop)
1697 if (pcop->type == PO_GPR_BIT) {
1698 char *name = pcop->name;
1700 name = PCOR(pcop)->r->name;
1701 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1702 switch(PCORB(pcop)->bit) {
1716 /*-----------------------------------------------------------------*/
1717 /* newpCode - create and return a newly initialized pCode */
1719 /* fixme - rename this */
1721 /* The purpose of this routine is to create a new Instruction */
1722 /* pCode. This is called by gen.c while the assembly code is being */
1726 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1727 /* (note that the op is analogous to but not the */
1728 /* same thing as the opcode of the instruction.) */
1729 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1732 /* a pointer to the new malloc'd pCode is returned. */
1736 /*-----------------------------------------------------------------*/
1737 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1739 pCodeInstruction *pci ;
1741 if(!mnemonics_initialized)
1742 pic14initMnemonics();
1744 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1746 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1747 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1748 pci->pc.id = PCodeID();
1751 if(pci->inCond & PCC_EXAMINE_PCOP)
1752 pci->inCond |= RegCond(pcop);
1754 if(pci->outCond & PCC_EXAMINE_PCOP)
1755 pci->outCond |= RegCond(pcop);
1757 pci->pc.prev = pci->pc.next = NULL;
1758 return (pCode *)pci;
1761 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1767 /*-----------------------------------------------------------------*/
1768 /* newpCodeWild - create a "wild" as in wild card pCode */
1770 /* Wild pcodes are used during the peep hole optimizer to serve */
1771 /* as place holders for any instruction. When a snippet of code is */
1772 /* compared to a peep hole rule, the wild card opcode will match */
1773 /* any instruction. However, the optional operand and label are */
1774 /* additional qualifiers that must also be matched before the */
1775 /* line (of assembly code) is declared matched. Note that the */
1776 /* operand may be wild too. */
1778 /* Note, a wild instruction is specified just like a wild var: */
1779 /* %4 ; A wild instruction, */
1780 /* See the peeph.def file for additional examples */
1782 /*-----------------------------------------------------------------*/
1784 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1789 pcw = Safe_calloc(1,sizeof(pCodeWild));
1791 pcw->pci.pc.type = PC_WILD;
1792 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1793 pcw->id = PCodeID();
1794 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1795 pcw->pci.pc.pb = NULL;
1797 // pcw->pci.pc.analyze = genericAnalyze;
1798 pcw->pci.pc.destruct = genericDestruct;
1799 pcw->pci.pc.print = genericPrint;
1801 pcw->id = pCodeID; // this is the 'n' in %n
1802 pcw->operand = optional_operand;
1803 pcw->label = optional_label;
1805 pcw->mustBeBitSkipInst = 0;
1806 pcw->mustNotBeBitSkipInst = 0;
1807 pcw->invertBitSkipInst = 0;
1809 return ( (pCode *)pcw);
1813 /*-----------------------------------------------------------------*/
1814 /* newPcodeInlineP - create a new pCode from a char string */
1815 /*-----------------------------------------------------------------*/
1818 pCode *newpCodeInlineP(char *cP)
1823 pcc = Safe_calloc(1,sizeof(pCodeComment));
1825 pcc->pc.type = PC_INLINE;
1826 pcc->pc.prev = pcc->pc.next = NULL;
1827 pcc->pc.id = PCodeID();
1828 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1831 // pcc->pc.analyze = genericAnalyze;
1832 pcc->pc.destruct = genericDestruct;
1833 pcc->pc.print = genericPrint;
1836 pcc->comment = Safe_strdup(cP);
1838 pcc->comment = NULL;
1840 return ( (pCode *)pcc);
1844 /*-----------------------------------------------------------------*/
1845 /* newPcodeCharP - create a new pCode from a char string */
1846 /*-----------------------------------------------------------------*/
1848 pCode *newpCodeCharP(char *cP)
1853 pcc = Safe_calloc(1,sizeof(pCodeComment));
1855 pcc->pc.type = PC_COMMENT;
1856 pcc->pc.prev = pcc->pc.next = NULL;
1857 pcc->pc.id = PCodeID();
1858 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1861 // pcc->pc.analyze = genericAnalyze;
1862 pcc->pc.destruct = genericDestruct;
1863 pcc->pc.print = genericPrint;
1866 pcc->comment = Safe_strdup(cP);
1868 pcc->comment = NULL;
1870 return ( (pCode *)pcc);
1874 /*-----------------------------------------------------------------*/
1875 /* newpCodeFunction - */
1876 /*-----------------------------------------------------------------*/
1879 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1883 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1884 //_ALLOC(pcf,sizeof(pCodeFunction));
1886 pcf->pc.type = PC_FUNCTION;
1887 pcf->pc.prev = pcf->pc.next = NULL;
1888 pcf->pc.id = PCodeID();
1889 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1892 // pcf->pc.analyze = genericAnalyze;
1893 pcf->pc.destruct = genericDestruct;
1894 pcf->pc.print = pCodePrintFunction;
1899 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1900 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1901 strcpy(pcf->modname,mod);
1903 pcf->modname = NULL;
1906 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1907 pcf->fname = Safe_calloc(1,strlen(f)+1);
1908 strcpy(pcf->fname,f);
1912 pcf->isPublic = (unsigned)isPublic;
1914 return ( (pCode *)pcf);
1918 /*-----------------------------------------------------------------*/
1920 /*-----------------------------------------------------------------*/
1921 void destructpCodeFlow(pCode *pc)
1923 if(!pc || !isPCFL(pc))
1932 deleteSet(&PCFL(pc)->registers);
1933 deleteSet(&PCFL(pc)->from);
1934 deleteSet(&PCFL(pc)->to);
1939 pCode *newpCodeFlow(void )
1943 //_ALLOC(pcflow,sizeof(pCodeFlow));
1944 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1946 pcflow->pc.type = PC_FLOW;
1947 pcflow->pc.prev = pcflow->pc.next = NULL;
1948 pcflow->pc.pb = NULL;
1950 // pcflow->pc.analyze = genericAnalyze;
1951 pcflow->pc.destruct = destructpCodeFlow;
1952 pcflow->pc.print = genericPrint;
1954 pcflow->pc.seq = GpcFlowSeq++;
1956 pcflow->from = pcflow->to = NULL;
1958 pcflow->inCond = PCC_NONE;
1959 pcflow->outCond = PCC_NONE;
1961 pcflow->firstBank = 'U'; /* Undetermined */
1962 pcflow->lastBank = 'U'; /* Undetermined */
1964 pcflow->FromConflicts = 0;
1965 pcflow->ToConflicts = 0;
1969 pcflow->registers = newSet();
1971 return ( (pCode *)pcflow);
1975 /*-----------------------------------------------------------------*/
1976 /*-----------------------------------------------------------------*/
1977 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1979 pCodeFlowLink *pcflowLink;
1981 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1983 pcflowLink->pcflow = pcflow;
1984 pcflowLink->bank_conflict = 0;
1989 /*-----------------------------------------------------------------*/
1990 /* newpCodeCSource - create a new pCode Source Symbol */
1991 /*-----------------------------------------------------------------*/
1993 pCode *newpCodeCSource(int ln, char *f, char *l)
1998 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2000 pccs->pc.type = PC_CSOURCE;
2001 pccs->pc.prev = pccs->pc.next = NULL;
2002 pccs->pc.id = PCodeID();
2005 pccs->pc.destruct = genericDestruct;
2006 pccs->pc.print = genericPrint;
2008 pccs->line_number = ln;
2010 pccs->line = Safe_strdup(l);
2015 pccs->file_name = Safe_strdup(f);
2017 pccs->file_name = NULL;
2019 return ( (pCode *)pccs);
2022 /*-----------------------------------------------------------------*/
2023 /* pCodeLabelDestruct - free memory used by a label. */
2024 /*-----------------------------------------------------------------*/
2025 static void pCodeLabelDestruct(pCode *pc)
2031 if((pc->type == PC_LABEL) && PCL(pc)->label)
2032 free(PCL(pc)->label);
2038 pCode *newpCodeLabel(char *name, int key)
2044 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2046 pcl->pc.type = PC_LABEL;
2047 pcl->pc.prev = pcl->pc.next = NULL;
2048 pcl->pc.id = PCodeID();
2049 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2052 // pcl->pc.analyze = genericAnalyze;
2053 pcl->pc.destruct = pCodeLabelDestruct;
2054 pcl->pc.print = pCodePrintLabel;
2060 sprintf(s,"_%05d_DS_",key);
2065 pcl->label = Safe_strdup(s);
2067 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2068 return ( (pCode *)pcl);
2073 /*-----------------------------------------------------------------*/
2074 /* newpBlock - create and return a pointer to a new pBlock */
2075 /*-----------------------------------------------------------------*/
2076 pBlock *newpBlock(void)
2081 PpB = Safe_calloc(1,sizeof(pBlock) );
2082 PpB->next = PpB->prev = NULL;
2084 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2085 PpB->tregisters = NULL;
2087 PpB->FlowTree = NULL;
2093 /*-----------------------------------------------------------------*/
2094 /* newpCodeChain - create a new chain of pCodes */
2095 /*-----------------------------------------------------------------*
2097 * This function will create a new pBlock and the pointer to the
2098 * pCode that is passed in will be the first pCode in the block.
2099 *-----------------------------------------------------------------*/
2102 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2105 pBlock *pB = newpBlock();
2107 pB->pcHead = pB->pcTail = pc;
2114 /*-----------------------------------------------------------------*/
2115 /* newpCodeOpLabel - Create a new label given the key */
2116 /* Note, a negative key means that the label is part of wild card */
2117 /* (and hence a wild card label) used in the pCodePeep */
2118 /* optimizations). */
2119 /*-----------------------------------------------------------------*/
2121 pCodeOp *newpCodeOpLabel(char *name, int key)
2124 static int label_key=-1;
2128 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2129 pcop->type = PO_LABEL;
2134 sprintf(s=buffer,"_%05d_DS_",key);
2136 s = name, key = label_key--;
2138 PCOLAB(pcop)->offset = 0;
2140 pcop->name = Safe_strdup(s);
2142 ((pCodeOpLabel *)pcop)->key = key;
2144 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2148 /*-----------------------------------------------------------------*/
2149 /*-----------------------------------------------------------------*/
2150 pCodeOp *newpCodeOpLit(int lit)
2156 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2157 pcop->type = PO_LITERAL;
2161 sprintf(s,"0x%02x",lit);
2163 pcop->name = Safe_strdup(s);
2166 ((pCodeOpLit *)pcop)->lit = lit;
2171 /*-----------------------------------------------------------------*/
2172 /*-----------------------------------------------------------------*/
2173 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2177 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2178 pcop->type = PO_IMMEDIATE;
2181 pcop->name = Safe_strdup(name);
2184 r = dirregWithName(name);
2188 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2189 PCOI(pcop)->rIdx = r->rIdx;
2191 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2192 PCOI(pcop)->rIdx = -1;
2194 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2199 PCOI(pcop)->index = index;
2200 PCOI(pcop)->offset = offset;
2201 PCOI(pcop)->_const = code_space;
2202 PCOI(pcop)->_function = is_func;
2207 /*-----------------------------------------------------------------*/
2208 /*-----------------------------------------------------------------*/
2209 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2215 if(!pcwb || !subtype) {
2216 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2220 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2221 pcop->type = PO_WILD;
2222 sprintf(s,"%%%d",id);
2223 pcop->name = Safe_strdup(s);
2225 PCOW(pcop)->id = id;
2226 PCOW(pcop)->pcwb = pcwb;
2227 PCOW(pcop)->subtype = subtype;
2228 PCOW(pcop)->matched = NULL;
2232 /*-----------------------------------------------------------------*/
2233 /* Find a symbol with matching name */
2234 /*-----------------------------------------------------------------*/
2235 static symbol *symFindWithName(memmap * map, const char *name)
2239 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2240 if (sym->rname && (strcmp(sym->rname,name)==0))
2246 /*-----------------------------------------------------------------*/
2247 /*-----------------------------------------------------------------*/
2248 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2253 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2254 pcop->type = PO_GPR_BIT;
2256 PCORB(pcop)->bit = ibit;
2257 PCORB(pcop)->inBitSpace = inBitSpace;
2259 if (name) r = regFindWithName(name);
2261 // Register has not been allocated - check for symbol information
2263 sym = symFindWithName(bit, name);
2264 if (!sym) sym = symFindWithName(sfrbit, name);
2265 if (!sym) sym = symFindWithName(sfr, name);
2267 r = allocNewDirReg(sym->etype,name);
2273 PCOR(pcop)->rIdx = r->rIdx;
2275 pcop->name = Safe_strdup(name);
2276 PCOR(pcop)->r = NULL;
2277 PCOR(pcop)->rIdx = 0;
2282 /*-----------------------------------------------------------------*
2283 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2285 * If rIdx >=0 then a specific register from the set of registers
2286 * will be selected. If rIdx <0, then a new register will be searched
2288 *-----------------------------------------------------------------*/
2290 pCodeOp *newpCodeOpReg(int rIdx)
2294 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2299 PCOR(pcop)->rIdx = rIdx;
2300 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2302 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2305 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2309 pcop->type = PCOR(pcop)->r->pc_type;
2314 pCodeOp *newpCodeOpRegFromStr(char *name)
2318 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2319 PCOR(pcop)->r = allocRegByName(name, 1);
2320 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2321 pcop->type = PCOR(pcop)->r->pc_type;
2322 pcop->name = PCOR(pcop)->r->name;
2327 pCodeOp *newpCodeOpStr(char *name)
2331 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2332 pcop->type = PO_STR;
2333 pcop->name = Safe_strdup(name);
2335 PCOS(pcop)->isPublic = 0;
2341 /*-----------------------------------------------------------------*/
2342 /*-----------------------------------------------------------------*/
2344 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2351 pcop = newpCodeOpBit(name, -1,0);
2355 pcop = newpCodeOpLit(-1);
2359 pcop = newpCodeOpLabel(NULL,-1);
2363 pcop = newpCodeOpReg(-1);
2366 case PO_GPR_POINTER:
2367 case PO_GPR_REGISTER:
2369 pcop = newpCodeOpRegFromStr(name);
2371 pcop = newpCodeOpReg(-1);
2375 pcop = newpCodeOpStr(name);
2379 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2382 pcop->name = Safe_strdup(name);
2390 /*-----------------------------------------------------------------*/
2391 /*-----------------------------------------------------------------*/
2392 void pCodeConstString(char *name, char *value)
2396 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2401 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2405 sprintf(buffer,"; %s = %s",name,value);
2407 addpCode2pBlock(pb,newpCodeCharP(buffer));
2408 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2411 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2417 /*-----------------------------------------------------------------*/
2418 /*-----------------------------------------------------------------*/
2419 void pCodeReadCodeTable(void)
2423 fprintf(stderr, " %s\n",__FUNCTION__);
2425 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2429 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2430 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2431 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2432 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2434 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2435 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2436 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2437 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2442 /*-----------------------------------------------------------------*/
2443 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2444 /*-----------------------------------------------------------------*/
2445 void addpCode2pBlock(pBlock *pb, pCode *pc)
2452 /* If this is the first pcode to be added to a block that
2453 * was initialized with a NULL pcode, then go ahead and
2454 * make this pcode the head and tail */
2455 pb->pcHead = pb->pcTail = pc;
2458 pb->pcTail->next = pc;
2460 pc->prev = pb->pcTail;
2467 /*-----------------------------------------------------------------*/
2468 /* addpBlock - place a pBlock into the pFile */
2469 /*-----------------------------------------------------------------*/
2470 void addpBlock(pBlock *pb)
2472 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2475 /* First time called, we'll pass through here. */
2476 //_ALLOC(the_pFile,sizeof(pFile));
2477 the_pFile = Safe_calloc(1,sizeof(pFile));
2478 the_pFile->pbHead = the_pFile->pbTail = pb;
2479 the_pFile->functions = NULL;
2483 the_pFile->pbTail->next = pb;
2484 pb->prev = the_pFile->pbTail;
2486 the_pFile->pbTail = pb;
2489 /*-----------------------------------------------------------------*/
2490 /* removepBlock - remove a pBlock from the pFile */
2491 /*-----------------------------------------------------------------*/
2492 void removepBlock(pBlock *pb)
2500 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2502 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2505 if(pbs == the_pFile->pbHead)
2506 the_pFile->pbHead = pbs->next;
2508 if (pbs == the_pFile->pbTail)
2509 the_pFile->pbTail = pbs->prev;
2512 pbs->next->prev = pbs->prev;
2515 pbs->prev->next = pbs->next;
2522 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2526 /*-----------------------------------------------------------------*/
2527 /* printpCode - write the contents of a pCode to a file */
2528 /*-----------------------------------------------------------------*/
2529 void printpCode(FILE *of, pCode *pc)
2540 fprintf(of,"warning - unable to print pCode\n");
2543 /*-----------------------------------------------------------------*/
2544 /* printpBlock - write the contents of a pBlock to a file */
2545 /*-----------------------------------------------------------------*/
2546 void printpBlock(FILE *of, pBlock *pb)
2556 for(pc = pb->pcHead; pc; pc = pc->next)
2561 /*-----------------------------------------------------------------*/
2563 /* pCode processing */
2567 /*-----------------------------------------------------------------*/
2569 void unlinkpCode(pCode *pc)
2575 fprintf(stderr,"Unlinking: ");
2576 printpCode(stderr, pc);
2579 pc->prev->next = pc->next;
2581 pc->next->prev = pc->prev;
2583 pc->prev = pc->next = NULL;
2587 /*-----------------------------------------------------------------*/
2588 /*-----------------------------------------------------------------*/
2590 static void genericDestruct(pCode *pc)
2596 /* For instructions, tell the register (if there's one used)
2597 * that it's no longer needed */
2598 regs *reg = getRegFromInstruction(pc);
2600 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2603 /* Instead of deleting the memory used by this pCode, mark
2604 * the object as bad so that if there's a pointer to this pCode
2605 * dangling around somewhere then (hopefully) when the type is
2606 * checked we'll catch it.
2611 addpCode2pBlock(pb_dead_pcodes, pc);
2618 /*-----------------------------------------------------------------*/
2619 /* Copies the pCodeInstruction flow pointer from source pCode */
2620 /*-----------------------------------------------------------------*/
2621 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2623 pCodeFlow *pcflow = 0;
2624 for (p=pcs; p; p=p->prev) {
2626 pcflow = PCI(p)->pcflow;
2630 pcflow = (pCodeFlow*)p;
2634 PCI(pcd)->pcflow = pcflow;
2637 /*-----------------------------------------------------------------*/
2638 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2639 /* into the pCode chain containing pc1 */
2640 /*-----------------------------------------------------------------*/
2641 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2647 pc2->next = pc1->next;
2649 pc1->next->prev = pc2;
2655 /* If this is an instrution type propogate the flow */
2657 CopyFlow(PCI(pc2),pc1);
2660 /*------------------------------------------------------------------*/
2661 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2662 /* into the pCode chain containing pc1 */
2663 /*------------------------------------------------------------------*/
2664 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2670 pc2->prev = pc1->prev;
2672 pc1->prev->next = pc2;
2678 /* If this is an instrution type propogate the flow */
2680 CopyFlow(PCI(pc2),pc1);
2683 /*-----------------------------------------------------------------*/
2684 /* pCodeOpCopy - copy a pcode operator */
2685 /*-----------------------------------------------------------------*/
2686 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2688 pCodeOp *pcopnew=NULL;
2693 switch(pcop->type) {
2696 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2697 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2698 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2699 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2704 /* Here we expand the wild card into the appropriate type: */
2705 /* By recursively calling pCodeOpCopy */
2706 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2707 if(PCOW(pcop)->matched)
2708 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2711 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2712 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2713 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2720 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2721 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2722 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2726 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2727 PCOI(pcopnew)->index = PCOI(pcop)->index;
2728 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2729 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2730 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2734 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2735 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2736 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2741 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2742 PCOR(pcopnew)->r = PCOR(pcop)->r;
2743 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2744 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2748 case PO_GPR_POINTER:
2749 case PO_GPR_REGISTER:
2753 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2754 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2755 PCOR(pcopnew)->r = PCOR(pcop)->r;
2756 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2757 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2758 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2762 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2763 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2764 PCOR(pcopnew)->r = PCOR(pcop)->r;
2765 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2766 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2769 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2770 case PO_SFR_REGISTER:
2778 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2779 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2783 pcopnew->type = pcop->type;
2785 pcopnew->name = Safe_strdup(pcop->name);
2787 pcopnew->name = NULL;
2792 /*-----------------------------------------------------------------*/
2793 /* popCopyReg - copy a pcode operator */
2794 /*-----------------------------------------------------------------*/
2795 pCodeOp *popCopyReg(pCodeOpReg *pc)
2799 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2800 pcor->pcop.type = pc->pcop.type;
2802 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2803 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2805 pcor->pcop.name = NULL;
2808 pcor->rIdx = pc->rIdx;
2811 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2816 /*-----------------------------------------------------------------*/
2817 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2818 /*-----------------------------------------------------------------*/
2819 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2821 pCodeInstruction *new_pci;
2824 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2826 new_pci = PCI(newpCode(pci->op,pci->pcop));
2828 new_pci->pc.pb = pci->pc.pb;
2829 new_pci->from = pci->from;
2830 new_pci->to = pci->to;
2831 new_pci->label = pci->label;
2832 new_pci->pcflow = pci->pcflow;
2834 return PCODE(new_pci);
2837 /*-----------------------------------------------------------------*/
2838 /*-----------------------------------------------------------------*/
2839 void pCodeDeleteChain(pCode *f,pCode *t)
2844 DFPRINTF((stderr,"delete pCode:\n"));
2846 //f->print(stderr,f);
2847 //f->delete(f); this dumps core...
2852 /*-----------------------------------------------------------------*/
2853 /*-----------------------------------------------------------------*/
2854 void pBlockRegs(FILE *of, pBlock *pb)
2859 r = setFirstItem(pb->tregisters);
2861 r = setNextItem(pb->tregisters);
2866 /*-----------------------------------------------------------------*/
2867 /*-----------------------------------------------------------------*/
2868 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2873 int use_buffer = 1; // copy the string to the passed buffer pointer
2878 use_buffer = 0; // Don't bother copying the string to the buffer.
2882 switch(pcop->type) {
2886 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2889 //return PCOR(pcop)->r->name;
2893 if (PCOR(pcop)->r->type == REG_STK)
2894 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2896 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2899 SAFE_snprintf(&buffer,&size,"%s",r->name);
2909 if(PCOI(pcop)->_const) {
2911 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2912 switch(PCOI(pcop)->offset) {
2914 SAFE_snprintf(&s,&size,"low %s",pcop->name);
2917 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2920 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2923 8 * PCOI(pcop)->offset );
2926 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2929 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2930 SAFE_snprintf(&s,&size,"(%s + %d)",
2932 PCOI(pcop)->index );
2934 switch(PCOI(pcop)->offset) {
2936 SAFE_snprintf(&s,&size,"%s",pcop->name);
2939 SAFE_snprintf(&s,&size,"high %s",pcop->name);
2942 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2951 //size = sizeof(buffer);
2952 if( PCOR(pcop)->instance) {
2953 SAFE_snprintf(&s,&size,"(%s + %d)",
2955 PCOR(pcop)->instance );
2956 //fprintf(stderr,"PO_DIR %s\n",buffer);
2958 SAFE_snprintf(&s,&size,"%s",pcop->name);
2964 if(PCOLAB(pcop)->offset == 1)
2965 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2967 SAFE_snprintf(&s,&size,"%s",pcop->name);
2974 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2983 return "NO operand";
2987 /*-----------------------------------------------------------------*/
2988 /*-----------------------------------------------------------------*/
2989 static char *get_op_from_instruction( pCodeInstruction *pcc)
2993 return get_op(pcc->pcop,NULL,0);
2995 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
2996 return ("ERROR Null: "__FUNCTION__);
2998 return ("ERROR Null: get_op_from_instruction");
3002 /*-----------------------------------------------------------------*/
3003 /*-----------------------------------------------------------------*/
3004 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3007 fprintf(of,"pcodeopprint- not implemented\n");
3010 /*-----------------------------------------------------------------*/
3011 /*-----------------------------------------------------------------*/
3012 char *pCode2str(char *str, size_t size, pCode *pc)
3020 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3022 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3024 if(PCI(pc)->isBitInst) {
3025 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3026 char *name = PCI(pc)->pcop->name;
3028 name = PCOR(PCI(pc)->pcop)->r->name;
3029 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3030 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3032 SAFE_snprintf(&s,&size,"%s,%d", name,
3033 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3034 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3035 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3037 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3038 //PCI(pc)->pcop->t.bit );
3041 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3042 if( PCI(pc)->num_ops == 2)
3043 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3045 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3048 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3050 if( PCI(pc)->num_ops == 2)
3051 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3059 /* assuming that comment ends with a \n */
3060 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3064 /* assuming that inline code ends with a \n */
3065 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3069 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3072 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3075 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3078 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3081 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3085 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3092 /*-----------------------------------------------------------------*/
3093 /* genericPrint - the contents of a pCode to a file */
3094 /*-----------------------------------------------------------------*/
3095 static void genericPrint(FILE *of, pCode *pc)
3103 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3107 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3111 // If the opcode has a label, print that first
3113 pBranch *pbl = PCI(pc)->label;
3114 while(pbl && pbl->pc) {
3115 if(pbl->pc->type == PC_LABEL)
3116 pCodePrintLabel(of, pbl->pc);
3122 genericPrint(of,PCODE(PCI(pc)->cline));
3127 pCode2str(str, 256, pc);
3129 fprintf(of,"%s",str);
3133 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3135 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3140 pBranch *dpb = pc->to; // debug
3142 switch ( dpb->pc->type) {
3144 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3147 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3150 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3153 fprintf(of, "\t;flow");
3167 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3168 if(PCW(pc)->pci.label)
3169 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3171 if(PCW(pc)->operand) {
3172 fprintf(of,";\toperand ");
3173 pCodeOpPrint(of,PCW(pc)->operand );
3179 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3180 if(PCFL(pc)->ancestor)
3181 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3188 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3192 fprintf(of,"unknown pCode type %d\n",pc->type);
3197 /*-----------------------------------------------------------------*/
3198 /* pCodePrintFunction - prints function begin/end */
3199 /*-----------------------------------------------------------------*/
3201 static void pCodePrintFunction(FILE *of, pCode *pc)
3207 if( ((pCodeFunction *)pc)->modname)
3208 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3210 if(PCF(pc)->fname) {
3211 pBranch *exits = PCF(pc)->to;
3213 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3216 exits = exits->next;
3219 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3222 if((PCF(pc)->from &&
3223 PCF(pc)->from->pc->type == PC_FUNCTION &&
3224 PCF(PCF(pc)->from->pc)->fname) )
3225 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3227 fprintf(of,"; exit point [can't find entry point]\n");
3230 /*-----------------------------------------------------------------*/
3231 /* pCodePrintLabel - prints label */
3232 /*-----------------------------------------------------------------*/
3234 static void pCodePrintLabel(FILE *of, pCode *pc)
3241 fprintf(of,"%s\n",PCL(pc)->label);
3242 else if (PCL(pc)->key >=0)
3243 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3245 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3248 /*-----------------------------------------------------------------*/
3249 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3250 /* remove it if it is found. */
3251 /*-----------------------------------------------------------------*/
3252 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3259 if(pcl->type == PC_OPCODE)
3260 b = PCI(pcl)->label;
3262 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3267 //fprintf (stderr, "%s \n",__FUNCTION__);
3268 //pcl->print(stderr,pcl);
3269 //pc->print(stderr,pc);
3272 //fprintf (stderr, "found label\n");
3276 bprev->next = b->next; /* Not first pCode in chain */
3280 PCI(pcl)->label = b->next; /* First pCode in chain */
3283 return; /* A label can't occur more than once */
3291 /*-----------------------------------------------------------------*/
3292 /*-----------------------------------------------------------------*/
3293 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3312 /*-----------------------------------------------------------------*/
3313 /* pBranchLink - given two pcodes, this function will link them */
3314 /* together through their pBranches */
3315 /*-----------------------------------------------------------------*/
3316 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3320 // Declare a new branch object for the 'from' pCode.
3322 //_ALLOC(b,sizeof(pBranch));
3323 b = Safe_calloc(1,sizeof(pBranch));
3324 b->pc = PCODE(t); // The link to the 'to' pCode.
3327 f->to = pBranchAppend(f->to,b);
3329 // Now do the same for the 'to' pCode.
3331 //_ALLOC(b,sizeof(pBranch));
3332 b = Safe_calloc(1,sizeof(pBranch));
3336 t->from = pBranchAppend(t->from,b);
3341 /*-----------------------------------------------------------------*/
3342 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3344 /*-----------------------------------------------------------------*/
3345 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3358 /*-----------------------------------------------------------------*/
3359 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3360 /*-----------------------------------------------------------------*/
3361 static void pCodeUnlink(pCode *pc)
3366 if(!pc->prev || !pc->next) {
3367 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3371 /* first remove the pCode from the chain */
3372 pc->prev->next = pc->next;
3373 pc->next->prev = pc->prev;
3375 /* Now for the hard part... */
3377 /* Remove the branches */
3381 pc1 = pb1->pc; /* Get the pCode that branches to the
3382 * one we're unlinking */
3384 /* search for the link back to this pCode (the one we're
3386 if(pb2 = pBranchFind(pc1->to,pc)) {
3387 pb2->pc = pc->to->pc; // make the replacement
3389 /* if the pCode we're unlinking contains multiple 'to'
3390 * branches (e.g. this a skip instruction) then we need
3391 * to copy these extra branches to the chain. */
3393 pBranchAppend(pb2, pc->to->next);
3402 /*-----------------------------------------------------------------*/
3403 /*-----------------------------------------------------------------*/
3405 static void genericAnalyze(pCode *pc)
3415 // Go through the pCodes that are in pCode chain and link
3416 // them together through the pBranches. Note, the pCodes
3417 // are linked together as a contiguous stream like the
3418 // assembly source code lines. The linking here mimics this
3419 // except that comments are not linked in.
3421 pCode *npc = pc->next;
3423 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3424 pBranchLink(pc,npc);
3429 /* reached the end of the pcode chain without finding
3430 * an instruction we could link to. */
3434 fprintf(stderr,"analyze PC_FLOW\n");
3438 fprintf(stderr,";A bad pCode is being used\n");
3444 /*-----------------------------------------------------------------*/
3445 /*-----------------------------------------------------------------*/
3446 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3450 if(pc->type == PC_LABEL) {
3451 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3454 if(pc->type == PC_OPCODE) {
3455 pbr = PCI(pc)->label;
3457 if(pbr->pc->type == PC_LABEL) {
3458 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3468 /*-----------------------------------------------------------------*/
3469 /*-----------------------------------------------------------------*/
3470 int checkLabel(pCode *pc)
3474 if(pc && isPCI(pc)) {
3475 pbr = PCI(pc)->label;
3477 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3487 /*-----------------------------------------------------------------*/
3488 /* findLabelinpBlock - Search the pCode for a particular label */
3489 /*-----------------------------------------------------------------*/
3490 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3497 for(pc = pb->pcHead; pc; pc = pc->next)
3498 if(compareLabel(pc,pcop_label))
3504 /*-----------------------------------------------------------------*/
3505 /* findLabel - Search the pCode for a particular label */
3506 /*-----------------------------------------------------------------*/
3507 pCode * findLabel(pCodeOpLabel *pcop_label)
3515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3516 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3520 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3524 /*-----------------------------------------------------------------*/
3525 /* findNextpCode - given a pCode, find the next of type 'pct' */
3526 /* in the linked list */
3527 /*-----------------------------------------------------------------*/
3528 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3541 /*-----------------------------------------------------------------*/
3542 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3543 /* in the linked list */
3544 /*-----------------------------------------------------------------*/
3545 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3557 /*-----------------------------------------------------------------*/
3558 /* findNextInstruction - given a pCode, find the next instruction */
3559 /* in the linked list */
3560 /*-----------------------------------------------------------------*/
3561 pCode * findNextInstruction(pCode *pci)
3566 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3570 fprintf(stderr,"findNextInstruction: ");
3571 printpCode(stderr, pc);
3576 //fprintf(stderr,"Couldn't find instruction\n");
3580 /*-----------------------------------------------------------------*/
3581 /* findNextInstruction - given a pCode, find the next instruction */
3582 /* in the linked list */
3583 /*-----------------------------------------------------------------*/
3584 pCode * findPrevInstruction(pCode *pci)
3586 return findPrevpCode(pci, PC_OPCODE);
3589 /*-----------------------------------------------------------------*/
3590 /* findFunctionEnd - given a pCode find the end of the function */
3591 /* that contains it */
3592 /*-----------------------------------------------------------------*/
3593 pCode * findFunctionEnd(pCode *pc)
3597 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3603 fprintf(stderr,"Couldn't find function end\n");
3608 /*-----------------------------------------------------------------*/
3609 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3610 /* instruction with which it is associated. */
3611 /*-----------------------------------------------------------------*/
3612 static void AnalyzeLabel(pCode *pc)
3621 static void AnalyzeGOTO(pCode *pc)
3624 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3628 static void AnalyzeSKIP(pCode *pc)
3631 pBranchLink(pc,findNextInstruction(pc->next));
3632 pBranchLink(pc,findNextInstruction(pc->next->next));
3636 static void AnalyzeRETURN(pCode *pc)
3639 // branch_link(pc,findFunctionEnd(pc->next));
3645 /*-----------------------------------------------------------------*/
3646 /*-----------------------------------------------------------------*/
3647 regs * getRegFromInstruction(pCode *pc)
3653 PCI(pc)->num_ops == 0 )
3656 switch(PCI(pc)->pcop->type) {
3659 return PCOR(PCI(pc)->pcop)->r;
3661 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3665 //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3666 return PCOR(PCI(pc)->pcop)->r;
3669 if(PCOI(PCI(pc)->pcop)->r)
3670 return (PCOI(PCI(pc)->pcop)->r);
3672 //fprintf(stderr, "getRegFromInstruction - immediate\n");
3673 return dirregWithName(PCI(pc)->pcop->name);
3674 //return NULL; // PCOR(PCI(pc)->pcop)->r;
3677 return PCOR(PCI(pc)->pcop)->r;
3679 case PO_GPR_REGISTER:
3681 //fprintf(stderr, "getRegFromInstruction - dir\n");
3682 return PCOR(PCI(pc)->pcop)->r;
3684 //fprintf(stderr, "getRegFromInstruction - literal\n");
3688 //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3689 //genericPrint(stderr, pc);
3697 /*-----------------------------------------------------------------*/
3698 /*-----------------------------------------------------------------*/
3700 void AnalyzepBlock(pBlock *pb)
3707 /* Find all of the registers used in this pBlock
3708 * by looking at each instruction and examining it's
3711 for(pc = pb->pcHead; pc; pc = pc->next) {
3713 /* Is this an instruction with operands? */
3714 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3716 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3717 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3719 /* Loop through all of the registers declared so far in
3720 this block and see if we find this one there */
3722 regs *r = setFirstItem(pb->tregisters);
3725 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3726 PCOR(PCI(pc)->pcop)->r = r;
3729 r = setNextItem(pb->tregisters);
3733 /* register wasn't found */
3734 //r = Safe_calloc(1, sizeof(regs));
3735 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3736 //addSet(&pb->tregisters, r);
3737 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3738 //PCOR(PCI(pc)->pcop)->r = r;
3739 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3741 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3744 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3745 if(PCOR(PCI(pc)->pcop)->r) {
3746 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3747 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3749 if(PCI(pc)->pcop->name)
3750 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3752 fprintf(stderr,"ERROR: NULL register\n");
3761 /*-----------------------------------------------------------------*/
3763 /*-----------------------------------------------------------------*/
3764 void InsertpFlow(pCode *pc, pCode **pflow)
3767 PCFL(*pflow)->end = pc;
3769 if(!pc || !pc->next)
3772 *pflow = newpCodeFlow();
3773 pCodeInsertAfter(pc, *pflow);
3776 /*-----------------------------------------------------------------*/
3777 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3778 /* the flow blocks. */
3780 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3781 * point the instruction flow changes.
3783 /*-----------------------------------------------------------------*/
3784 void BuildFlow(pBlock *pb)
3787 pCode *last_pci=NULL;
3794 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3795 /* Insert a pCodeFlow object at the beginning of a pBlock */
3797 InsertpFlow(pb->pcHead, &pflow);
3799 //pflow = newpCodeFlow(); /* Create a new Flow object */
3800 //pflow->next = pb->pcHead; /* Make the current head the next object */
3801 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3802 //pb->pcHead = pflow; /* Make the Flow object the head */
3805 for( pc = findNextInstruction(pb->pcHead);
3807 pc=findNextInstruction(pc)) {
3810 PCI(pc)->pcflow = PCFL(pflow);
3812 //fprintf(stderr," build: ");
3813 //pflow->print(stderr,pflow);
3815 if( PCI(pc)->isSkip) {
3817 /* The two instructions immediately following this one
3818 * mark the beginning of a new flow segment */
3820 while(pc && PCI(pc)->isSkip) {
3822 PCI(pc)->pcflow = PCFL(pflow);
3826 InsertpFlow(pc, &pflow);
3827 pc=findNextInstruction(pc->next);
3835 PCI(pc)->pcflow = PCFL(pflow);
3837 InsertpFlow(pc, &pflow);
3839 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3841 InsertpFlow(pc, &pflow);
3844 } else if (checkLabel(pc)) {
3846 /* This instruction marks the beginning of a
3847 * new flow segment */
3852 /* If the previous pCode is not a flow object, then
3853 * insert a new flow object. (This check prevents
3854 * two consecutive flow objects from being insert in
3855 * the case where a skip instruction preceeds an
3856 * instruction containing a label.) */
3858 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3859 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3861 PCI(pc)->pcflow = PCFL(pflow);
3868 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3870 PCFL(pflow)->end = pb->pcTail;
3873 /*-------------------------------------------------------------------*/
3874 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3875 /* the flow blocks. */
3877 * unBuildFlow removes pCodeFlow objects from a pCode chain
3879 /*-----------------------------------------------------------------*/
3880 void unBuildFlow(pBlock *pb)
3895 if(PCI(pc)->pcflow) {
3896 //free(PCI(pc)->pcflow);
3897 PCI(pc)->pcflow = NULL;
3900 } else if(isPCFL(pc) )
3909 /*-----------------------------------------------------------------*/
3910 /*-----------------------------------------------------------------*/
3911 void dumpCond(int cond)
3914 static char *pcc_str[] = {
3928 int ncond = sizeof(pcc_str) / sizeof(char *);
3931 fprintf(stderr, "0x%04X\n",cond);
3933 for(i=0,j=1; i<ncond; i++, j<<=1)
3935 fprintf(stderr, " %s\n",pcc_str[i]);
3939 /*-----------------------------------------------------------------*/
3940 /*-----------------------------------------------------------------*/
3941 void FlowStats(pCodeFlow *pcflow)
3949 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3951 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3954 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3959 fprintf(stderr, " FlowStats inCond: ");
3960 dumpCond(pcflow->inCond);
3961 fprintf(stderr, " FlowStats outCond: ");
3962 dumpCond(pcflow->outCond);
3966 /*-----------------------------------------------------------------*
3967 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3968 * if it affects the banking bits.
3970 * return: -1 == Banking bits are unaffected by this pCode.
3972 * return: > 0 == Banking bits are affected.
3974 * If the banking bits are affected, then the returned value describes
3975 * which bits are affected and how they're affected. The lower half
3976 * of the integer maps to the bits that are affected, the upper half
3977 * to whether they're set or cleared.
3979 *-----------------------------------------------------------------*/
3981 #define SET_BANK_BIT (1 << 16)
3982 #define CLR_BANK_BIT 0
3984 static int isBankInstruction(pCode *pc)
3992 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3994 // Check to see if the register banks are changing
3995 if(PCI(pc)->isModReg) {
3997 pCodeOp *pcop = PCI(pc)->pcop;
3998 switch(PCI(pc)->op) {
4001 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4002 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4003 return SET_BANK_BIT | PIC_RP0_BIT;
4006 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4007 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4008 return CLR_BANK_BIT | PIC_RP0_BIT;
4013 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4014 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4015 return CLR_BANK_BIT | PIC_RP1_BIT;
4017 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4018 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4019 return CLR_BANK_BIT | PIC_RP1_BIT;
4023 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4024 //genericPrint(stderr, pc);
4035 /*-----------------------------------------------------------------*/
4036 /*-----------------------------------------------------------------*/
4038 static void FillFlow(pCodeFlow *pcflow)
4046 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4048 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4051 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4058 isBankInstruction(pc);
4060 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4063 fprintf(stderr, " FillFlow - Bad end of flow\n");
4065 fprintf(stderr, " FillFlow - Ending flow with\n ");
4066 pc->print(stderr,pc);
4069 fprintf(stderr, " FillFlow inCond: ");
4070 dumpCond(pcflow->inCond);
4071 fprintf(stderr, " FillFlow outCond: ");
4072 dumpCond(pcflow->outCond);
4077 /*-----------------------------------------------------------------*/
4078 /*-----------------------------------------------------------------*/
4079 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4081 pCodeFlowLink *fromLink, *toLink;
4083 if(!from || !to || !to->pcflow || !from->pcflow)
4086 fromLink = newpCodeFlowLink(from->pcflow);
4087 toLink = newpCodeFlowLink(to->pcflow);
4089 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4090 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4094 /*-----------------------------------------------------------------*
4095 * void LinkFlow(pBlock *pb)
4097 * In BuildFlow, the PIC code has been partitioned into contiguous
4098 * non-branching segments. In LinkFlow, we determine the execution
4099 * order of these segments. For example, if one of the segments ends
4100 * with a skip, then we know that there are two possible flow segments
4101 * to which control may be passed.
4102 *-----------------------------------------------------------------*/
4103 void LinkFlow(pBlock *pb)
4109 //fprintf(stderr,"linkflow \n");
4111 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4113 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4116 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4118 //fprintf(stderr," link: ");
4119 //pcflow->print(stderr,pcflow);
4121 //FillFlow(PCFL(pcflow));
4123 pc = PCFL(pcflow)->end;
4125 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4126 if(isPCI_SKIP(pc)) {
4127 //fprintf(stderr, "ends with skip\n");
4128 //pc->print(stderr,pc);
4129 pct=findNextInstruction(pc->next);
4130 LinkFlow_pCode(PCI(pc),PCI(pct));
4131 pct=findNextInstruction(pct->next);
4132 LinkFlow_pCode(PCI(pc),PCI(pct));
4136 if(isPCI_BRANCH(pc)) {
4137 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4139 //fprintf(stderr, "ends with branch\n ");
4140 //pc->print(stderr,pc);
4142 if(!(pcol && isPCOLAB(pcol))) {
4143 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4144 pc->print(stderr,pc);
4145 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4150 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4151 LinkFlow_pCode(PCI(pc),PCI(pct));
4153 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4154 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4155 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4161 //fprintf(stderr, "ends with non-branching instruction:\n");
4162 //pc->print(stderr,pc);
4164 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4170 //fprintf(stderr, "ends with unknown\n");
4171 //pc->print(stderr,pc);
4175 //fprintf(stderr, "ends with nothing: ERROR\n");
4179 /*-----------------------------------------------------------------*/
4180 /*-----------------------------------------------------------------*/
4182 /*-----------------------------------------------------------------*/
4183 /*-----------------------------------------------------------------*/
4184 int isPCinFlow(pCode *pc, pCode *pcflow)
4190 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4193 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4199 /*-----------------------------------------------------------------*/
4200 /*-----------------------------------------------------------------*/
4202 static void BanksUsedFlow2(pCode *pcflow)
4211 if(!isPCFL(pcflow)) {
4212 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4216 pc = findNextInstruction(pcflow->next);
4218 PCFL(pcflow)->lastBank = -1;
4220 while(isPCinFlow(pc,pcflow)) {
4222 int bank_selected = isBankInstruction(pc);
4224 //if(PCI(pc)->pcflow)
4225 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4227 if(bank_selected > 0) {
4228 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4230 // This instruction is modifying banking bits before accessing registers
4232 PCFL(pcflow)->firstBank = -1;
4234 if(PCFL(pcflow)->lastBank == -1)
4235 PCFL(pcflow)->lastBank = 0;
4237 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4238 if(bank_selected & SET_BANK_BIT)
4239 PCFL(pcflow)->lastBank |= bank;
4243 reg = getRegFromInstruction(pc);
4245 if(reg && !isREGinBank(reg, bank)) {
4246 int allbanks = REGallBanks(reg);
4248 PCFL(pcflow)->firstBank = allbanks;
4250 PCFL(pcflow)->lastBank = allbanks;
4257 pc = findNextInstruction(pc->next);
4260 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4261 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4264 /*-----------------------------------------------------------------*/
4265 /*-----------------------------------------------------------------*/
4267 static void BanksUsedFlow(pBlock *pb)
4272 //pb->pcHead->print(stderr, pb->pcHead);
4274 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4275 //pcflow->print(stderr,pcflow);
4277 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4279 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4281 BanksUsedFlow2(pcflow);
4287 /*-----------------------------------------------------------------*/
4288 /*-----------------------------------------------------------------*/
4289 static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci)
4292 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4294 /* Move the label, if there is one */
4297 new_pci->label = pci->label;
4301 /* Move the C code comment, if there is one */
4304 new_pci->cline = pci->cline;
4308 /* The new instruction has the same pcflow block */
4309 new_pci->pcflow = pci->pcflow;
4313 /*-----------------------------------------------------------------*/
4314 /*-----------------------------------------------------------------*/
4315 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4319 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4321 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4324 /*-----------------------------------------------------------------*/
4325 /*-----------------------------------------------------------------*/
4326 static void insertBankSel(pCodeInstruction *pci, const char *name)
4330 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4331 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4332 if (pcop->name == 0)
4333 pcop->name = strdup(name);
4334 new_pc = newpCode(POC_BANKSEL, pcop);
4336 pCodeInstructionInsertAfter(pci, PCI(new_pc));
4339 /*-----------------------------------------------------------------*/
4340 /* If the register is a fixed known addess then we can assign the */
4341 /* bank selection bits. Otherwise the linker is going to assign */
4342 /* the register location and thus has to set bank selection bits */
4343 /* through the banksel directive. */
4344 /* One critical assumption here is that within this C module all */
4345 /* the locally allocated registers are in the same udata sector. */
4346 /* Therefore banksel is only called for external registers or the */
4347 /* first time a local register is encountered. */
4348 /*-----------------------------------------------------------------*/
4349 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4350 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4353 int a = reg->alias>>7;
4355 return cur_bank; // This register is available in all banks
4356 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4357 return cur_bank; // This register is available in banks 0 & 1
4359 if (reg->address&0x80) {
4360 if ((cur_bank==1)||(cur_bank==3)) {
4361 return cur_bank; // This register is available in banks 1 & 3
4364 if ((cur_bank==0)||(cur_bank==1)) {
4365 return cur_bank; // This register is available in banks 0 & 2
4370 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4372 LastRegIdx = reg->rIdx;
4375 bank = REG_BANK(reg);
4376 } else if (reg->isExtern) {
4377 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4379 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4381 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.
4382 return 'L'; // Local registers are presumed to be in same linker assigned bank
4383 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4384 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4385 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4386 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4387 } 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
4388 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4389 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4390 } else { // Current bank and new register banks known - can set bank bits
4391 switch((cur_bank^bank) & 3) {
4395 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4398 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4401 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4402 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4410 /*-----------------------------------------------------------------*/
4411 /* Check for bank selection pcodes instructions and modify */
4412 /* cur_bank to match. */
4413 /*-----------------------------------------------------------------*/
4414 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4416 if (isSTATUS_REG(reg)) {
4418 if (PCI(pc)->op == POC_BCF) {
4419 int old_bank = *cur_bank;
4420 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4421 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4422 if (*cur_bank & ~(0x3))
4425 *cur_bank = *cur_bank&0x2;
4426 LastRegIdx = reg->rIdx;
4427 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4428 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4429 if (*cur_bank & ~(0x3))
4432 *cur_bank = *cur_bank&0x1;
4433 LastRegIdx = reg->rIdx;
4435 return old_bank != *cur_bank;
4438 if (PCI(pc)->op == POC_BSF) {
4439 int old_bank = *cur_bank;
4440 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4441 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4442 if (*cur_bank & ~(0x3))
4445 *cur_bank = (*cur_bank&0x2) | 0x1;
4446 LastRegIdx = reg->rIdx;
4447 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4448 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4449 if (*cur_bank & ~(0x3))
4452 *cur_bank = (*cur_bank&0x1) | 0x2;
4453 LastRegIdx = reg->rIdx;
4455 return old_bank != *cur_bank;
4458 } else if (PCI(pc)->op == POC_BANKSEL) {
4459 int old_bank = *cur_bank;
4460 *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L';
4461 LastRegIdx = reg->rIdx;
4462 return old_bank != *cur_bank;
4468 /*-----------------------------------------------------------------*/
4469 /* Set bank selection if necessary */
4470 /*-----------------------------------------------------------------*/
4471 static int DoBankSelect(pCode *pc, int cur_bank) {
4479 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4480 if (pcf && isPCF(pcf)) {
4482 int rbank = 'U'; // Undetermined
4483 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4484 // Check all the returns to work out what bank is selected
4485 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4487 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4489 rbank = PCFL(pcfr)->lastBank;
4491 if (rbank != PCFL(pcfr)->lastBank)
4492 return -1; // Unknown bank - multiple returns with different banks
4497 return -1; // Unknown bank
4499 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4500 /* Extern functions may use registers in different bank - must call banksel */
4501 return -1; /* Unknown bank */
4505 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4506 return -1; /* New bank unknown - linkers choice. */
4509 reg = getRegFromInstruction(pc);
4512 if (IsBankChange(pc,reg,&cur_bank))
4515 if (!isPCI_LIT(pc)) {
4517 /* Examine the instruction before this one to make sure it is
4518 * not a skip type instruction */
4519 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4521 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4522 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4524 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4526 if (!PCI(pc)->pcflow)
4527 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4529 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4535 /*-----------------------------------------------------------------*/
4536 /*-----------------------------------------------------------------*/
4538 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4546 pc = findNextInstruction(pcfl->pc.next);
4548 while(isPCinFlow(pc,PCODE(pcfl))) {
4550 cur_bank = DoBankSelect(pc,cur_bank);
4552 pc = findNextInstruction(pc->next);
4556 if(pcprev && cur_bank) {
4557 // Set bank state to unknown at the end of each flow block
4563 /*-----------------------------------------------------------------*/
4564 /*int compareBankFlow - compare the banking requirements between */
4566 /*-----------------------------------------------------------------*/
4568 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4571 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4574 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4577 if(pcflow->firstBank == -1)
4581 if(pcflowLink->pcflow->firstBank == -1) {
4582 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4583 pcflowLink->pcflow->to :
4584 pcflowLink->pcflow->from);
4585 return compareBankFlow(pcflow, pctl, toORfrom);
4589 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4592 pcflowLink->bank_conflict++;
4593 pcflowLink->pcflow->FromConflicts++;
4594 pcflow->ToConflicts++;
4597 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4600 pcflowLink->bank_conflict++;
4601 pcflowLink->pcflow->ToConflicts++;
4602 pcflow->FromConflicts++;
4606 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4607 pcflowLink->pcflow->pc.seq,
4608 pcflowLink->pcflow->FromConflicts,
4609 pcflowLink->pcflow->ToConflicts);
4615 /*-----------------------------------------------------------------*/
4616 /*-----------------------------------------------------------------*/
4618 void FixBankFlow(pBlock *pb)
4622 pCodeFlowLink *pcfl;
4624 pCode *pcflow_max_To=NULL;
4625 pCode *pcflow_max_From=NULL;
4626 int max_ToConflicts=0;
4627 int max_FromConflicts=0;
4629 //fprintf(stderr,"Fix Bank flow \n");
4630 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4634 First loop through all of the flow objects in this pcode block
4635 and fix the ones that have banking conflicts between the
4639 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4641 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4643 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4645 if(!isPCFL(pcflow)) {
4646 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4650 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4651 PCFL(pcflow)->firstBank >= 0 &&
4652 PCFL(pcflow)->lastBank >= 0 ) {
4654 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4655 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4657 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4658 BanksUsedFlow2(pcflow);
4663 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4665 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4667 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4672 if(!isPCFL(pcflow)) {
4673 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4677 PCFL(pcflow)->FromConflicts = 0;
4678 PCFL(pcflow)->ToConflicts = 0;
4683 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4684 pcfl = setFirstItem(PCFL(pcflow)->from);
4687 pc = PCODE(pcfl->pcflow);
4690 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4691 pc->print(stderr,pc);
4694 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4697 pcfl=setNextItem(PCFL(pcflow)->from);
4700 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4701 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4703 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4704 BanksUsedFlow2(pcflow);
4706 continue; / * Don't need to check the flow from here - it's already been fixed * /
4713 pcfl = setFirstItem(PCFL(pcflow)->to);
4716 pc = PCODE(pcfl->pcflow);
4718 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4719 pc->print(stderr,pc);
4722 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4725 pcfl=setNextItem(PCFL(pcflow)->to);
4728 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4729 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4731 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4732 BanksUsedFlow2(pcflow);
4737 Loop through the flow objects again and find the ones with the
4741 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4743 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4745 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4746 pcflow_max_To = pcflow;
4748 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4749 pcflow_max_From = pcflow;
4753 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4754 PCFL(pcflow_max_To)->pc.seq,
4755 PCFL(pcflow_max_To)->ToConflicts);
4758 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4759 PCFL(pcflow_max_From)->pc.seq,
4760 PCFL(pcflow_max_From)->FromConflicts);
4765 /*-----------------------------------------------------------------*/
4766 /*-----------------------------------------------------------------*/
4767 void DumpFlow(pBlock *pb)
4771 pCodeFlowLink *pcfl;
4774 fprintf(stderr,"Dump flow \n");
4775 pb->pcHead->print(stderr, pb->pcHead);
4777 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4778 pcflow->print(stderr,pcflow);
4780 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4782 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4784 if(!isPCFL(pcflow)) {
4785 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4788 fprintf(stderr,"dumping: ");
4789 pcflow->print(stderr,pcflow);
4790 FlowStats(PCFL(pcflow));
4792 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4794 pc = PCODE(pcfl->pcflow);
4796 fprintf(stderr, " from seq %d:\n",pc->seq);
4798 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4799 pc->print(stderr,pc);
4804 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4806 pc = PCODE(pcfl->pcflow);
4808 fprintf(stderr, " to seq %d:\n",pc->seq);
4810 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4811 pc->print(stderr,pc);
4820 /*-----------------------------------------------------------------*/
4821 /*-----------------------------------------------------------------*/
4822 int OptimizepBlock(pBlock *pb)
4827 if(!pb || !peepOptimizing)
4830 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4832 for(pc = pb->pcHead; pc; pc = pc->next)
4833 matches += pCodePeepMatchRule(pc);
4836 pc = findNextInstruction(pb->pcHead);
4844 if(pCodePeepMatchRule(pc)) {
4849 pc = findNextInstruction(pcprev->next);
4851 pc = findNextInstruction(pb->pcHead);
4853 pc = findNextInstruction(pc->next);
4857 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4862 /*-----------------------------------------------------------------*/
4863 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4864 /*-----------------------------------------------------------------*/
4865 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4869 for(pc = pcs; pc; pc = pc->next) {
4871 if((pc->type == PC_OPCODE) &&
4873 (PCI(pc)->pcop->type == PO_LABEL) &&
4874 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4882 /*-----------------------------------------------------------------*/
4883 /*-----------------------------------------------------------------*/
4884 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4891 (PCI(pc)->pcop->type == PO_LABEL)) {
4893 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4895 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4897 free(pcol->pcop.name);
4899 /* If the key is negative, then we (probably) have a label to
4900 * a function and the name is already defined */
4903 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4907 //sprintf(buffer,"_%05d_DS_",pcl->key);
4909 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4911 pcol->pcop.name = Safe_strdup(s);
4912 pcol->key = pcl->key;
4913 //pc->print(stderr,pc);
4920 /*-----------------------------------------------------------------*/
4921 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4922 /* pCode chain if they're not used. */
4923 /*-----------------------------------------------------------------*/
4924 void pBlockRemoveUnusedLabels(pBlock *pb)
4926 pCode *pc; pCodeLabel *pcl;
4931 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4933 pBranch *pbr = PCI(pc)->label;
4934 if(pbr && pbr->next) {
4935 pCode *pcd = pb->pcHead;
4937 //fprintf(stderr, "multiple labels\n");
4938 //pc->print(stderr,pc);
4943 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4944 //fprintf(stderr,"Used by:\n");
4945 //pcd->print(stderr,pcd);
4947 exchangeLabels(PCL(pbr->pc),pcd);
4956 for(pc = pb->pcHead; pc; pc = pc->next) {
4958 if(isPCL(pc)) // Label pcode
4960 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4961 pcl = PCL(PCI(pc)->label->pc);
4964 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4966 /* This pCode is a label, so search the pBlock to see if anyone
4969 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4970 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4971 /* Couldn't find an instruction that refers to this label
4972 * So, unlink the pCode label from it's pCode chain
4973 * and destroy the label */
4974 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4976 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4977 if(pc->type == PC_LABEL) {
4979 pCodeLabelDestruct(pc);
4981 unlinkpCodeFromBranch(pc, PCODE(pcl));
4982 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4993 /*-----------------------------------------------------------------*/
4994 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4995 /* chain and put them into pBranches that are */
4996 /* associated with the appropriate pCode */
4998 /*-----------------------------------------------------------------*/
4999 void pBlockMergeLabels(pBlock *pb)
5002 pCode *pc, *pcnext=NULL;
5007 /* First, Try to remove any unused labels */
5008 //pBlockRemoveUnusedLabels(pb);
5010 /* Now loop through the pBlock and merge the labels with the opcodes */
5013 // for(pc = pb->pcHead; pc; pc = pc->next) {
5016 pCode *pcn = pc->next;
5018 if(pc->type == PC_LABEL) {
5020 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5021 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5022 if((pcnext = findNextInstruction(pc) )) {
5024 // Unlink the pCode label from it's pCode chain
5027 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5028 // And link it into the instruction's pBranch labels. (Note, since
5029 // it's possible to have multiple labels associated with one instruction
5030 // we must provide a means to accomodate the additional labels. Thus
5031 // the labels are placed into the singly-linked list "label" as
5032 // opposed to being a single member of the pCodeInstruction.)
5034 //_ALLOC(pbr,sizeof(pBranch));
5035 pbr = Safe_calloc(1,sizeof(pBranch));
5039 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5042 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5044 } else if(pc->type == PC_CSOURCE) {
5046 /* merge the source line symbolic info into the next instruction */
5047 if((pcnext = findNextInstruction(pc) )) {
5049 // Unlink the pCode label from it's pCode chain
5051 PCI(pcnext)->cline = PCCS(pc);
5052 //fprintf(stderr, "merging CSRC\n");
5053 //genericPrint(stderr,pcnext);
5059 pBlockRemoveUnusedLabels(pb);
5063 /*-----------------------------------------------------------------*/
5064 /*-----------------------------------------------------------------*/
5065 int OptimizepCode(char dbName)
5067 #define MAX_PASSES 4
5076 DFPRINTF((stderr," Optimizing pCode\n"));
5080 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5081 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5082 matches += OptimizepBlock(pb);
5085 while(matches && ++passes < MAX_PASSES);
5090 /*-----------------------------------------------------------------*/
5091 /* popCopyGPR2Bit - copy a pcode operator */
5092 /*-----------------------------------------------------------------*/
5094 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5098 pcop = newpCodeOpBit(pc->name, bitval, 0);
5100 if( !( (pcop->type == PO_LABEL) ||
5101 (pcop->type == PO_LITERAL) ||
5102 (pcop->type == PO_STR) ))
5103 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5109 /*-----------------------------------------------------------------*/
5110 /*-----------------------------------------------------------------*/
5111 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5114 int firstBank = 'U';
5119 for (pc=pb->pcHead; pc; pc=pc->next) {
5121 firstBank = PCFL(pc)->firstBank;
5125 if (firstBank != 'U') {
5126 /* This block has already been done */
5127 if (firstBank != cur_bank) {
5128 /* This block has started with a different bank - must adjust it */
5129 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5132 regs *reg = getRegFromInstruction(pc);
5134 DoBankSelect(pc,cur_bank);
5144 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5147 for (pc=pb->pcHead; pc; pc=pc->next) {
5149 PCFL(pc)->firstBank = cur_bank;
5152 cur_bank = DoBankSelect(pc,cur_bank);
5155 /* Trace through branches and set the bank selection as required. */
5158 for (pc=pb->pcHead; pc; pc=pc->next) {
5160 PCFL(pc)->firstBank = cur_bank;
5164 if (PCI(pc)->op == POC_GOTO) {
5165 int lastRegIdx = LastRegIdx;
5167 /* Trace through branch */
5168 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5171 regs *reg = getRegFromInstruction(pcl);
5173 int bankUnknown = -1;
5174 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5176 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5182 LastRegIdx = lastRegIdx;
5184 /* Keep track out current bank */
5185 regs *reg = getRegFromInstruction(pc);
5187 IsBankChange(pc,reg,&cur_bank);
5194 /*-----------------------------------------------------------------*/
5195 /*-----------------------------------------------------------------*/
5196 void pBlockDestruct(pBlock *pb)
5207 /*-----------------------------------------------------------------*/
5208 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5209 /* name dbName and combine them */
5210 /* into one block */
5211 /*-----------------------------------------------------------------*/
5212 void mergepBlocks(char dbName)
5215 pBlock *pb, *pbmerged = NULL,*pbn;
5217 pb = the_pFile->pbHead;
5219 //fprintf(stderr," merging blocks named %c\n",dbName);
5223 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5224 if( getpBlock_dbName(pb) == dbName) {
5226 //fprintf(stderr," merged block %c\n",dbName);
5231 addpCode2pBlock(pbmerged, pb->pcHead);
5232 /* addpCode2pBlock doesn't handle the tail: */
5233 pbmerged->pcTail = pb->pcTail;
5235 pb->prev->next = pbn;
5237 pbn->prev = pb->prev;
5242 //printpBlock(stderr, pbmerged);
5249 /*-----------------------------------------------------------------*/
5250 /* AnalyzeFlow - Examine the flow of the code and optimize */
5252 /* level 0 == minimal optimization */
5253 /* optimize registers that are used only by two instructions */
5254 /* level 1 == maximal optimization */
5255 /* optimize by looking at pairs of instructions that use the */
5257 /*-----------------------------------------------------------------*/
5259 void AnalyzeFlow(int level)
5261 static int times_called=0;
5269 /* if this is not the first time this function has been called,
5270 then clean up old flow information */
5271 if(times_called++) {
5272 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5275 RegsUnMapLiveRanges();
5281 /* Phase 2 - Flow Analysis - Register Banking
5283 * In this phase, the individual flow blocks are examined
5284 * and register banking is fixed.
5287 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5288 //FixRegisterBanking(pb);
5290 /* Phase 2 - Flow Analysis
5292 * In this phase, the pCode is partition into pCodeFlow
5293 * blocks. The flow blocks mark the points where a continuous
5294 * stream of instructions changes flow (e.g. because of
5295 * a call or goto or whatever).
5298 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5302 /* Phase 2 - Flow Analysis - linking flow blocks
5304 * In this phase, the individual flow blocks are examined
5305 * to determine their order of excution.
5308 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5311 /* Phase 3 - Flow Analysis - Flow Tree
5313 * In this phase, the individual flow blocks are examined
5314 * to determine their order of excution.
5317 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5321 /* Phase x - Flow Analysis - Used Banks
5323 * In this phase, the individual flow blocks are examined
5324 * to determine the Register Banks they use
5327 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5331 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5332 pCodeRegMapLiveRanges(pb);
5334 RemoveUnusedRegisters();
5336 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5337 pCodeRegOptimizeRegUsage(level);
5343 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5348 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5350 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5351 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5352 pcflow = pcflow->next) {
5354 FillFlow(PCFL(pcflow));
5359 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5361 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5362 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5363 pcflow = pcflow->next) {
5365 FlowStats(PCFL(pcflow));
5371 /*-----------------------------------------------------------------*/
5372 /* AnalyzeBanking - Called after the memory addresses have been */
5373 /* assigned to the registers. */
5375 /*-----------------------------------------------------------------*/
5377 void AnalyzeBanking(void)
5381 if(!picIsInitialized()) {
5382 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5383 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5384 fprintf(stderr,"support/scripts/inc2h.pl\n");
5385 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5390 /* Phase x - Flow Analysis - Used Banks
5392 * In this phase, the individual flow blocks are examined
5393 * to determine the Register Banks they use
5399 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5400 // BanksUsedFlow(pb);
5401 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5402 FixRegisterBanking(pb,-1); // cur_bank is unknown
5406 /*-----------------------------------------------------------------*/
5407 /*-----------------------------------------------------------------*/
5408 DEFSETFUNC (resetrIdx)
5410 if (!((regs *)item)->isFixed)
5411 ((regs *)item)->rIdx = 0;
5416 /*-----------------------------------------------------------------*/
5417 /* InitRegReuse - Initialises variables for code analyzer */
5418 /*-----------------------------------------------------------------*/
5420 void InitReuseReg(void)
5422 /* Find end of statically allocated variables for start idx */
5423 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5425 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5426 if (r->type != REG_SFR) {
5427 maxIdx += r->size; /* Increment for all statically allocated variables */
5431 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5434 /*-----------------------------------------------------------------*/
5435 /*-----------------------------------------------------------------*/
5436 static unsigned register_reassign(pBlock *pb, unsigned idx)
5440 /* check recursion */
5441 pc = setFirstItem(pb->function_entries);
5447 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5449 if (pb->tregisters) {
5451 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5452 if (r->type == REG_GPR) {
5454 if (r->rIdx < (int)idx) {
5457 if (peakIdx < idx) peakIdx = idx;
5458 sprintf(s,"r0x%02X", r->rIdx);
5459 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5461 r->name = Safe_strdup(s);
5467 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5469 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5470 char *dest = get_op_from_instruction(PCI(pc));
5472 pCode *pcn = findFunction(dest);
5474 register_reassign(pcn->pb,idx);
5483 /*------------------------------------------------------------------*/
5484 /* ReuseReg were call tree permits */
5486 /* Re-allocate the GPR for optimum reuse for a given pblock */
5487 /* eg if a function m() calls function f1() and f2(), where f1 */
5488 /* allocates a local variable vf1 and f2 allocates a local */
5489 /* variable vf2. Then providing f1 and f2 do not call each other */
5490 /* they may share the same general purpose registers for vf1 and */
5492 /* This is done by first setting the the regs rIdx to start after */
5493 /* all the global variables, then walking through the call tree */
5494 /* renaming the registers to match their new idx and incrementng */
5495 /* it as it goes. If a function has already been called it will */
5496 /* only rename the registers if it has already used up those */
5497 /* registers ie rIdx of the function's registers is lower than the */
5498 /* current rIdx. That way the register will not be reused while */
5499 /* still being used by an eariler function call. */
5501 /* Note for this to work the fucntions need to be declared static. */
5503 /*------------------------------------------------------------------*/
5508 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5509 /* Non static functions can be called from other modules so their registers must reassign */
5510 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5511 register_reassign(pb,peakIdx);
5515 /*-----------------------------------------------------------------*/
5516 /* buildCallTree - look at the flow and extract all of the calls */
5518 /*-----------------------------------------------------------------*/
5520 void buildCallTree(void )
5529 /* Now build the call tree.
5530 First we examine all of the pCodes for functions.
5531 Keep in mind that the function boundaries coincide
5532 with pBlock boundaries.
5534 The algorithm goes something like this:
5535 We have two nested loops. The outer loop iterates
5536 through all of the pBlocks/functions. The inner
5537 loop iterates through all of the pCodes for
5538 a given pBlock. When we begin iterating through
5539 a pBlock, the variable pc_fstart, pCode of the start
5540 of a function, is cleared. We then search for pCodes
5541 of type PC_FUNCTION. When one is encountered, we
5542 initialize pc_fstart to this and at the same time
5543 associate a new pBranch object that signifies a
5544 branch entry. If a return is found, then this signifies
5545 a function exit point. We'll link the pCodes of these
5546 returns to the matching pc_fstart.
5548 When we're done, a doubly linked list of pBranches
5549 will exist. The head of this list is stored in
5550 `the_pFile', which is the meta structure for all
5551 of the pCode. Look at the printCallTree function
5552 on how the pBranches are linked together.
5555 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5556 pCode *pc_fstart=NULL;
5557 for(pc = pb->pcHead; pc; pc = pc->next) {
5559 pCodeFunction *pcf = PCF(pc);
5562 if(STRCASECMP(pcf->fname, "_main") == 0) {
5563 //fprintf(stderr," found main \n");
5564 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5568 pbr = Safe_calloc(1,sizeof(pBranch));
5569 pbr->pc = pc_fstart = pc;
5572 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5574 // Here's a better way of doing the same:
5575 addSet(&pb->function_entries, pc);
5578 // Found an exit point in a function, e.g. return
5579 // (Note, there may be more than one return per function)
5581 pBranchLink(PCF(pc_fstart), pcf);
5583 addSet(&pb->function_exits, pc);
5585 } else if(isCALL(pc)) {
5586 addSet(&pb->function_calls,pc);
5592 /*-----------------------------------------------------------------*/
5593 /* AnalyzepCode - parse the pCode that has been generated and form */
5594 /* all of the logical connections. */
5596 /* Essentially what's done here is that the pCode flow is */
5598 /*-----------------------------------------------------------------*/
5600 void AnalyzepCode(char dbName)
5611 /* Phase 1 - Register allocation and peep hole optimization
5613 * The first part of the analysis is to determine the registers
5614 * that are used in the pCode. Once that is done, the peep rules
5615 * are applied to the code. We continue to loop until no more
5616 * peep rule optimizations are found (or until we exceed the
5617 * MAX_PASSES threshold).
5619 * When done, the required registers will be determined.
5625 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5627 /* First, merge the labels with the instructions */
5628 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5629 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5631 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5632 pBlockMergeLabels(pb);
5635 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5639 changes = OptimizepCode(dbName);
5641 } while(changes && (i++ < MAX_PASSES));
5646 /*-----------------------------------------------------------------*/
5647 /* ispCodeFunction - returns true if *pc is the pCode of a */
5649 /*-----------------------------------------------------------------*/
5650 bool ispCodeFunction(pCode *pc)
5653 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5659 /*-----------------------------------------------------------------*/
5660 /* findFunction - Search for a function by name (given the name) */
5661 /* in the set of all functions that are in a pBlock */
5662 /* (note - I expect this to change because I'm planning to limit */
5663 /* pBlock's to just one function declaration */
5664 /*-----------------------------------------------------------------*/
5665 pCode *findFunction(char *fname)
5672 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5674 pc = setFirstItem(pb->function_entries);
5677 if((pc->type == PC_FUNCTION) &&
5679 (strcmp(fname, PCF(pc)->fname)==0))
5682 pc = setNextItem(pb->function_entries);
5690 void MarkUsedRegisters(set *regset)
5695 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5696 r2 = pic14_regWithIdx(r1->rIdx);
5704 void pBlockStats(FILE *of, pBlock *pb)
5710 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5712 // for now just print the first element of each set
5713 pc = setFirstItem(pb->function_entries);
5715 fprintf(of,";entry: ");
5718 pc = setFirstItem(pb->function_exits);
5720 fprintf(of,";has an exit\n");
5724 pc = setFirstItem(pb->function_calls);
5726 fprintf(of,";functions called:\n");
5729 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5730 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5732 pc = setNextItem(pb->function_calls);
5736 r = setFirstItem(pb->tregisters);
5738 int n = elementsInSet(pb->tregisters);
5740 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5743 fprintf(of,"; %s\n",r->name);
5744 r = setNextItem(pb->tregisters);
5749 /*-----------------------------------------------------------------*/
5750 /*-----------------------------------------------------------------*/
5752 static void sequencepCode(void)
5758 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5760 pb->seq = GpCodeSequenceNumber+1;
5762 for( pc = pb->pcHead; pc; pc = pc->next)
5763 pc->seq = ++GpCodeSequenceNumber;
5769 /*-----------------------------------------------------------------*/
5770 /*-----------------------------------------------------------------*/
5772 set *register_usage(pBlock *pb)
5775 set *registers=NULL;
5776 set *registersInCallPath = NULL;
5778 / * check recursion * /
5780 pc = setFirstItem(pb->function_entries);
5787 if(pc->type != PC_FUNCTION)
5788 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5790 pc = setFirstItem(pb->function_calls);
5791 for( ; pc; pc = setNextItem(pb->function_calls)) {
5793 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5794 char *dest = get_op_from_instruction(PCI(pc));
5796 pcn = findFunction(dest);
5798 registersInCallPath = register_usage(pcn->pb);
5800 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5805 pBlockStats(stderr,pb); // debug
5808 // Mark the registers in this block as used.
5810 MarkUsedRegisters(pb->tregisters);
5811 if(registersInCallPath) {
5812 / * registers were used in the functions this pBlock has called * /
5813 / * so now, we need to see if these collide with the ones we are * /
5816 regs *r1,*r2, *newreg;
5818 DFPRINTF((stderr,"comparing registers\n"));
5820 r1 = setFirstItem(registersInCallPath);
5822 if (r1->type != REG_STK) {
5823 r2 = setFirstItem(pb->tregisters);
5825 while(r2 && (r2->type != REG_STK)) {
5827 if(r2->rIdx == r1->rIdx) {
5828 newreg = pic14_findFreeReg(REG_GPR);
5832 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5836 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5837 r1->rIdx, newreg->rIdx));
5838 r2->rIdx = newreg->rIdx;
5840 r2->name = Safe_strdup(newreg->name);
5844 newreg->wasUsed = 1;
5846 r2 = setNextItem(pb->tregisters);
5850 r1 = setNextItem(registersInCallPath);
5853 / * Collisions have been resolved. Now free the registers in the call path * /
5854 r1 = setFirstItem(registersInCallPath);
5856 newreg = pic14_regWithIdx(r1->rIdx);
5857 if (newreg) newreg->isFree = 1;
5858 r1 = setNextItem(registersInCallPath);
5862 // MarkUsedRegisters(pb->registers);
5864 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5867 DFPRINTF((stderr,"returning regs\n"));
5869 DFPRINTF((stderr,"not returning regs\n"));
5871 DFPRINTF((stderr,"pBlock after register optim.\n"));
5872 pBlockStats(stderr,pb); // debug
5879 /*-----------------------------------------------------------------*/
5880 /* printCallTree - writes the call tree to a file */
5882 /*-----------------------------------------------------------------*/
5883 void pct2(FILE *of,pBlock *pb,int indent)
5887 // set *registersInCallPath = NULL;
5893 return; //recursion ?
5895 pc = setFirstItem(pb->function_entries);
5902 for(i=0;i<indent;i++) // Indentation
5905 if(pc->type == PC_FUNCTION)
5906 fprintf(of,"%s\n",PCF(pc)->fname);
5911 pc = setFirstItem(pb->function_calls);
5912 for( ; pc; pc = setNextItem(pb->function_calls)) {
5914 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5915 char *dest = get_op_from_instruction(PCI(pc));
5917 pcn = findFunction(dest);
5919 pct2(of,pcn->pb,indent+1);
5921 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5929 /*-----------------------------------------------------------------*/
5930 /* printCallTree - writes the call tree to a file */
5932 /*-----------------------------------------------------------------*/
5934 void printCallTree(FILE *of)
5946 fprintf(of, "\npBlock statistics\n");
5947 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5952 fprintf(of,"Call Tree\n");
5953 pbr = the_pFile->functions;
5957 if(!ispCodeFunction(pc))
5958 fprintf(of,"bug in call tree");
5961 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5963 while(pc->next && !ispCodeFunction(pc->next)) {
5965 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5966 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5974 fprintf(of,"\n**************\n\na better call tree\n");
5975 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5980 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5981 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5987 /*-----------------------------------------------------------------*/
5989 /*-----------------------------------------------------------------*/
5991 void InlineFunction(pBlock *pb)
5999 pc = setFirstItem(pb->function_calls);
6001 for( ; pc; pc = setNextItem(pb->function_calls)) {
6004 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6005 pCode *pcp = pc->prev;
6011 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 */
6013 InlineFunction(pcn->pb);
6016 At this point, *pc points to a CALL mnemonic, and
6017 *pcn points to the function that is being called.
6019 To in-line this call, we need to remove the CALL
6020 and RETURN(s), and link the function pCode in with
6027 /* Check if previous instruction was a bit skip */
6028 if (isPCI_BITSKIP(pcp)) {
6030 /* Invert skip instruction and add a goto */
6031 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6033 if(isPCL(pc_call->next)) { // Label pcode
6034 pcl = PCL(pc_call->next);
6035 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6036 pcl = PCL(PCI(pc_call->next)->label->pc);
6038 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6039 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6041 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6044 /* remove callee pBlock from the pBlock linked list */
6045 removepBlock(pcn->pb);
6053 /* Remove the Function pCode */
6054 pct = findNextInstruction(pcn->next);
6056 /* Link the function with the callee */
6057 if (pcp) pcp->next = pcn->next;
6058 pcn->next->prev = pcp;
6060 /* Convert the function name into a label */
6062 pbr = Safe_calloc(1,sizeof(pBranch));
6063 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6065 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6066 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6068 /* turn all of the return's except the last into goto's */
6069 /* check case for 2 instruction pBlocks */
6070 pce = findNextInstruction(pcn->next);
6072 pCode *pce_next = findNextInstruction(pce->next);
6074 if(pce_next == NULL) {
6075 /* found the last return */
6076 pCode *pc_call_next = findNextInstruction(pc_call->next);
6078 //fprintf(stderr,"found last return\n");
6079 //pce->print(stderr,pce);
6080 pce->prev->next = pc_call->next;
6081 pc_call->next->prev = pce->prev;
6082 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6091 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6097 /*-----------------------------------------------------------------*/
6099 /*-----------------------------------------------------------------*/
6101 void InlinepCode(void)
6110 if(!functionInlining)
6113 /* Loop through all of the function definitions and count the
6114 * number of times each one is called */
6115 //fprintf(stderr,"inlining %d\n",__LINE__);
6117 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6119 pc = setFirstItem(pb->function_calls);
6121 for( ; pc; pc = setNextItem(pb->function_calls)) {
6124 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6125 if(pcn && isPCF(pcn)) {
6126 PCF(pcn)->ncalled++;
6129 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6134 //fprintf(stderr,"inlining %d\n",__LINE__);
6136 /* Now, Loop through the function definitions again, but this
6137 * time inline those functions that have only been called once. */
6139 InlineFunction(the_pFile->pbHead);
6140 //fprintf(stderr,"inlining %d\n",__LINE__);
6142 for(pb = the_pFile->pbHead; pb; pb = pb->next)