1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 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 functionInlining = 1; /* inline functions if nonzero */
79 int debug_verbose = 0; /* Set true to inundate .asm file */
81 // static int GpCodeSequenceNumber = 1;
84 /* statistics (code size estimation) */
85 static unsigned int pcode_insns = 0;
86 static unsigned int pcode_doubles = 0;
89 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
90 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
92 extern void RemoveUnusedRegisters(void);
93 extern void RegsUnMapLiveRanges(void);
94 extern void BuildFlowTree(pBlock *pb);
95 extern void pCodeRegOptimizeRegUsage(int level);
96 extern int picIsInitialized(void);
97 extern const char *pCodeOpType(pCodeOp *pcop);
99 /****************************************************************/
100 /* Forward declarations */
101 /****************************************************************/
103 void unlinkpCode(pCode *pc);
105 static void genericAnalyze(pCode *pc);
106 static void AnalyzeGOTO(pCode *pc);
107 static void AnalyzeSKIP(pCode *pc);
108 static void AnalyzeRETURN(pCode *pc);
111 static void genericDestruct(pCode *pc);
112 static void genericPrint(FILE *of,pCode *pc);
114 static void pCodePrintLabel(FILE *of, pCode *pc);
115 static void pCodePrintFunction(FILE *of, pCode *pc);
116 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
117 static char *get_op_from_instruction( pCodeInstruction *pcc);
118 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
119 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
120 int pCodePeepMatchRule(pCode *pc);
121 void pBlockStats(FILE *of, pBlock *pb);
122 pBlock *newpBlock(void);
123 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
124 void pCodeRegMapLiveRanges(pBlock *pb);
126 pBranch * pBranchAppend(pBranch *h, pBranch *n);
129 /****************************************************************/
130 /* PIC Instructions */
131 /****************************************************************/
133 pCodeInstruction pciADDWF = {
134 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
147 1,0, // dest, bit instruction
149 0, // literal operand
151 (PCC_W | PCC_REGISTER), // inCond
152 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
155 pCodeInstruction pciADDFW = {
156 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
169 0,0, // dest, bit instruction
171 0, // literal operand
173 (PCC_W | PCC_REGISTER), // inCond
174 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
177 pCodeInstruction pciADDLW = {
178 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
191 0,0, // dest, bit instruction
193 1, // literal operand
195 (PCC_W | PCC_LITERAL), // inCond
196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
199 pCodeInstruction pciANDLW = {
200 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
213 0,0, // dest, bit instruction
215 1, // literal operand
217 (PCC_W | PCC_LITERAL), // inCond
218 (PCC_W | PCC_Z) // outCond
221 pCodeInstruction pciANDWF = {
222 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
235 1,0, // dest, bit instruction
237 0, // literal operand
239 (PCC_W | PCC_REGISTER), // inCond
240 (PCC_REGISTER | PCC_Z) // outCond
243 pCodeInstruction pciANDFW = {
244 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
257 0,0, // dest, bit instruction
259 0, // literal operand
261 (PCC_W | PCC_REGISTER), // inCond
262 (PCC_W | PCC_Z) // outCond
265 pCodeInstruction pciBCF = {
266 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
279 1,1, // dest, bit instruction
281 0, // literal operand
283 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
284 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
287 pCodeInstruction pciBSF = {
288 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
301 1,1, // dest, bit instruction
303 0, // literal operand
305 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
306 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
309 pCodeInstruction pciBTFSC = {
310 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
323 0,1, // dest, bit instruction
325 0, // literal operand
327 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
331 pCodeInstruction pciBTFSS = {
332 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
345 0,1, // dest, bit instruction
347 0, // literal operand
349 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
353 pCodeInstruction pciCALL = {
354 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
367 0,0, // dest, bit instruction
369 0, // literal operand
371 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
372 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
375 pCodeInstruction pciCOMF = {
376 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
389 1,0, // dest, bit instruction
391 0, // literal operand
393 PCC_REGISTER, // inCond
394 PCC_REGISTER | PCC_Z // outCond
397 pCodeInstruction pciCOMFW = {
398 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
411 0,0, // dest, bit instruction
413 0, // literal operand
415 PCC_REGISTER, // inCond
416 PCC_W | PCC_Z // outCond
419 pCodeInstruction pciCLRF = {
420 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
433 0,0, // dest, bit instruction
435 0, // literal operand
438 PCC_REGISTER | PCC_Z // outCond
441 pCodeInstruction pciCLRW = {
442 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
455 0,0, // dest, bit instruction
457 0, // literal operand
460 PCC_W | PCC_Z // outCond
463 pCodeInstruction pciCLRWDT = {
464 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
477 0,0, // dest, bit instruction
479 0, // literal operand
485 pCodeInstruction pciDECF = {
486 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
499 1,0, // dest, bit instruction
501 0, // literal operand
503 PCC_REGISTER, // inCond
504 PCC_REGISTER | PCC_Z // outCond
507 pCodeInstruction pciDECFW = {
508 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
521 0,0, // dest, bit instruction
523 0, // literal operand
525 PCC_REGISTER, // inCond
526 PCC_W | PCC_Z // outCond
529 pCodeInstruction pciDECFSZ = {
530 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
543 1,0, // dest, bit instruction
545 0, // literal operand
547 PCC_REGISTER, // inCond
548 PCC_REGISTER // outCond
551 pCodeInstruction pciDECFSZW = {
552 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
565 0,0, // dest, bit instruction
567 0, // literal operand
569 PCC_REGISTER, // inCond
573 pCodeInstruction pciGOTO = {
574 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
587 0,0, // dest, bit instruction
589 0, // literal operand
595 pCodeInstruction pciINCF = {
596 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
609 1,0, // dest, bit instruction
611 0, // literal operand
613 PCC_REGISTER, // inCond
614 PCC_REGISTER | PCC_Z // outCond
617 pCodeInstruction pciINCFW = {
618 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
631 0,0, // dest, bit instruction
633 0, // literal operand
635 PCC_REGISTER, // inCond
636 PCC_W | PCC_Z // outCond
639 pCodeInstruction pciINCFSZ = {
640 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
653 1,0, // dest, bit instruction
655 0, // literal operand
657 PCC_REGISTER, // inCond
658 PCC_REGISTER // outCond
661 pCodeInstruction pciINCFSZW = {
662 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
675 0,0, // dest, bit instruction
677 0, // literal operand
679 PCC_REGISTER, // inCond
683 pCodeInstruction pciIORWF = {
684 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
697 1,0, // dest, bit instruction
699 0, // literal operand
701 (PCC_W | PCC_REGISTER), // inCond
702 (PCC_REGISTER | PCC_Z) // outCond
705 pCodeInstruction pciIORFW = {
706 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
719 0,0, // dest, bit instruction
721 0, // literal operand
723 (PCC_W | PCC_REGISTER), // inCond
724 (PCC_W | PCC_Z) // outCond
727 pCodeInstruction pciIORLW = {
728 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
741 0,0, // dest, bit instruction
743 1, // literal operand
745 (PCC_W | PCC_LITERAL), // inCond
746 (PCC_W | PCC_Z) // outCond
749 pCodeInstruction pciMOVF = {
750 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
763 1,0, // dest, bit instruction
765 0, // literal operand
767 PCC_REGISTER, // inCond
771 pCodeInstruction pciMOVFW = {
772 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
785 0,0, // dest, bit instruction
787 0, // literal operand
789 PCC_REGISTER, // inCond
790 (PCC_W | PCC_Z) // outCond
793 pCodeInstruction pciMOVWF = {
794 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
807 0,0, // dest, bit instruction
809 0, // literal operand
812 PCC_REGISTER // outCond
815 pCodeInstruction pciMOVLW = {
816 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
828 0,0, // dest, bit instruction
830 1, // literal operand
832 (PCC_NONE | PCC_LITERAL), // inCond
836 pCodeInstruction pciNOP = {
837 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
849 0,0, // dest, bit instruction
851 0, // literal operand
857 pCodeInstruction pciRETFIE = {
858 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
871 0,0, // dest, bit instruction
873 0, // literal operand
876 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
879 pCodeInstruction pciRETLW = {
880 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
893 0,0, // dest, bit instruction
895 1, // literal operand
897 PCC_LITERAL, // inCond
898 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
901 pCodeInstruction pciRETURN = {
902 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
915 0,0, // dest, bit instruction
917 0, // literal operand
919 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
920 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
923 pCodeInstruction pciRLF = {
924 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
937 1,0, // dest, bit instruction
939 0, // literal operand
941 (PCC_C | PCC_REGISTER), // inCond
942 (PCC_REGISTER | PCC_C ) // outCond
945 pCodeInstruction pciRLFW = {
946 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
959 0,0, // dest, bit instruction
961 0, // literal operand
963 (PCC_C | PCC_REGISTER), // inCond
964 (PCC_W | PCC_C) // outCond
967 pCodeInstruction pciRRF = {
968 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
981 1,0, // dest, bit instruction
983 0, // literal operand
985 (PCC_C | PCC_REGISTER), // inCond
986 (PCC_REGISTER | PCC_C) // outCond
989 pCodeInstruction pciRRFW = {
990 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1003 0,0, // dest, bit instruction
1004 0,0, // branch, skip
1005 0, // literal operand
1007 (PCC_C | PCC_REGISTER), // inCond
1008 (PCC_W | PCC_C) // outCond
1011 pCodeInstruction pciSUBWF = {
1012 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1018 NULL, // from branch
1025 1,0, // dest, bit instruction
1026 0,0, // branch, skip
1027 0, // literal operand
1029 (PCC_W | PCC_REGISTER), // inCond
1030 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1033 pCodeInstruction pciSUBFW = {
1034 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1040 NULL, // from branch
1047 0,0, // dest, bit instruction
1048 0,0, // branch, skip
1049 0, // literal operand
1051 (PCC_W | PCC_REGISTER), // inCond
1052 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1055 pCodeInstruction pciSUBLW = {
1056 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1062 NULL, // from branch
1069 0,0, // dest, bit instruction
1070 0,0, // branch, skip
1071 1, // literal operand
1073 (PCC_W | PCC_LITERAL), // inCond
1074 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1077 pCodeInstruction pciSWAPF = {
1078 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1084 NULL, // from branch
1091 1,0, // dest, bit instruction
1092 0,0, // branch, skip
1093 0, // literal operand
1095 (PCC_REGISTER), // inCond
1096 (PCC_REGISTER) // outCond
1099 pCodeInstruction pciSWAPFW = {
1100 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1106 NULL, // from branch
1113 0,0, // dest, bit instruction
1114 0,0, // branch, skip
1115 0, // literal operand
1117 (PCC_REGISTER), // inCond
1121 pCodeInstruction pciTRIS = {
1122 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1128 NULL, // from branch
1135 0,0, // dest, bit instruction
1136 0,0, // branch, skip
1137 0, // literal operand
1139 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1140 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1143 pCodeInstruction pciXORWF = {
1144 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1150 NULL, // from branch
1157 1,0, // dest, bit instruction
1158 0,0, // branch, skip
1159 0, // literal operand
1161 (PCC_W | PCC_REGISTER), // inCond
1162 (PCC_REGISTER | PCC_Z) // outCond
1165 pCodeInstruction pciXORFW = {
1166 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1172 NULL, // from branch
1179 0,0, // dest, bit instruction
1180 0,0, // branch, skip
1181 0, // literal operand
1183 (PCC_W | PCC_REGISTER), // inCond
1184 (PCC_W | PCC_Z) // outCond
1187 pCodeInstruction pciXORLW = {
1188 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1194 NULL, // from branch
1201 0,0, // dest, bit instruction
1202 0,0, // branch, skip
1203 1, // literal operand
1205 (PCC_W | PCC_LITERAL), // inCond
1206 (PCC_W | PCC_Z) // outCond
1210 pCodeInstruction pciBANKSEL = {
1211 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1217 NULL, // from branch
1224 0,0, // dest, bit instruction
1225 0,0, // branch, skip
1226 0, // literal operand
1232 pCodeInstruction pciPAGESEL = {
1233 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1239 NULL, // from branch
1246 0,0, // dest, bit instruction
1247 0,0, // branch, skip
1248 0, // literal operand
1254 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1257 /*-----------------------------------------------------------------*/
1258 /* return a unique ID number to assist pCodes debuging */
1259 /*-----------------------------------------------------------------*/
1260 unsigned PCodeID(void) {
1261 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1263 static unsigned int stop;
1264 if (pcodeId == 1448)
1265 stop++; // Place break point here
1270 #ifdef HAVE_VSNPRINTF
1271 // Alas, vsnprintf is not ANSI standard, and does not exist
1272 // on Solaris (and probably other non-Gnu flavored Unixes).
1274 /*-----------------------------------------------------------------*/
1275 /* SAFE_snprintf - like snprintf except the string pointer is */
1276 /* after the string has been printed to. This is */
1277 /* useful for printing to string as though if it */
1278 /* were a stream. */
1279 /*-----------------------------------------------------------------*/
1280 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1288 va_start(val, format);
1290 vsnprintf(*str, *size, format, val);
1295 if((size_t)len > *size) {
1296 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1297 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1305 #else // HAVE_VSNPRINTF
1307 // This version is *not* safe, despite the name.
1309 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1313 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1318 va_start(val, format);
1320 vsprintf(buffer, format, val);
1323 len = strlen(buffer);
1325 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1326 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1329 strcpy(*str, buffer);
1335 #endif // HAVE_VSNPRINTF
1338 extern void initStack(int base_address, int size);
1339 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1340 extern regs *allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias);
1341 extern void init_pic(char *);
1343 void pCodeInitRegisters(void)
1345 static int initialized=0;
1346 int shareBankAddress,stkSize;
1352 init_pic(port->processor);
1353 /* FIXME - some PIC ICs like 16C7X which do not have a shared bank
1354 * need a different approach.
1355 * The fixed address might not be needed anyway, possibly the
1356 * linker will assign udata_shr sections correctly... */
1357 shareBankAddress = pic14_getSharebankAddress();
1358 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1359 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1360 * (used for interrupts) to fit into the shared portion of the
1362 stkSize = pic14_getSharebankSize()-3;
1363 /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1364 initStack(shareBankAddress, stkSize);
1366 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1367 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1368 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1369 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1370 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1371 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1373 pc_status.rIdx = IDX_STATUS;
1374 pc_fsr.rIdx = IDX_FSR;
1375 pc_indf.rIdx = IDX_INDF;
1376 pc_intcon.rIdx = IDX_INTCON;
1377 pc_pcl.rIdx = IDX_PCL;
1378 pc_pclath.rIdx = IDX_PCLATH;
1380 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1381 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1382 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1384 pc_wsave.rIdx = pc_wsave.r->rIdx;
1385 pc_ssave.rIdx = pc_ssave.r->rIdx;
1386 pc_psave.rIdx = pc_psave.r->rIdx;
1388 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1389 pc_wsave.r->address = shareBankAddress-stkSize;
1390 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1391 pc_ssave.r->address = shareBankAddress-stkSize-1;
1392 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1393 pc_psave.r->address = shareBankAddress-stkSize-2;
1395 /* probably should put this in a separate initialization routine */
1396 pb_dead_pcodes = newpBlock();
1400 /*-----------------------------------------------------------------*/
1401 /* mnem2key - convert a pic mnemonic into a hash key */
1402 /* (BTW - this spreads the mnemonics quite well) */
1404 /*-----------------------------------------------------------------*/
1406 int mnem2key(unsigned char const *mnem)
1415 key += toupper(*mnem++) +1;
1419 return (key & 0x1f);
1423 void pic14initMnemonics(void)
1428 pCodeInstruction *pci;
1430 if(mnemonics_initialized)
1433 //FIXME - probably should NULL out the array before making the assignments
1434 //since we check the array contents below this initialization.
1436 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1437 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1438 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1439 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1440 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1441 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1442 pic14Mnemonics[POC_BCF] = &pciBCF;
1443 pic14Mnemonics[POC_BSF] = &pciBSF;
1444 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1445 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1446 pic14Mnemonics[POC_CALL] = &pciCALL;
1447 pic14Mnemonics[POC_COMF] = &pciCOMF;
1448 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1449 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1450 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1451 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1452 pic14Mnemonics[POC_DECF] = &pciDECF;
1453 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1454 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1455 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1456 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1457 pic14Mnemonics[POC_INCF] = &pciINCF;
1458 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1459 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1460 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1461 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1462 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1463 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1464 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1465 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1466 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1467 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1468 pic14Mnemonics[POC_NOP] = &pciNOP;
1469 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1470 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1471 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1472 pic14Mnemonics[POC_RLF] = &pciRLF;
1473 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1474 pic14Mnemonics[POC_RRF] = &pciRRF;
1475 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1476 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1477 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1478 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1479 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1480 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1481 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1482 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1483 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1484 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1485 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1486 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1488 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1489 if(pic14Mnemonics[i])
1490 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1491 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1494 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1495 pci = hTabNextItem(pic14MnemonicsHash, &key);
1498 mnemonics_initialized = 1;
1501 int getpCodePeepCommand(char *cmd);
1503 int getpCode(char *mnem,unsigned dest)
1506 pCodeInstruction *pci;
1507 int key = mnem2key((unsigned char *)mnem);
1509 if(!mnemonics_initialized)
1510 pic14initMnemonics();
1512 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1516 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1517 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1521 pci = hTabNextItemWK (pic14MnemonicsHash);
1528 /*-----------------------------------------------------------------*
1529 * pic14initpCodePeepCommands
1531 *-----------------------------------------------------------------*/
1532 void pic14initpCodePeepCommands(void)
1540 hTabAddItem(&pic14pCodePeepCommandsHash,
1541 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1543 } while (peepCommands[i].cmd);
1545 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1548 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1549 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1554 /*-----------------------------------------------------------------
1557 *-----------------------------------------------------------------*/
1559 int getpCodePeepCommand(char *cmd)
1563 int key = mnem2key((unsigned char *)cmd);
1566 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1569 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1570 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1574 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1581 char getpBlock_dbName(pBlock *pb)
1587 return pb->cmemmap->dbName;
1591 void pBlockConvert2ISR(pBlock *pb)
1602 /*-----------------------------------------------------------------*/
1603 /* movepBlock2Head - given the dbname of a pBlock, move all */
1604 /* instances to the front of the doubly linked */
1605 /* list of pBlocks */
1606 /*-----------------------------------------------------------------*/
1608 void movepBlock2Head(char dbName)
1615 pb = the_pFile->pbHead;
1619 if(getpBlock_dbName(pb) == dbName) {
1620 pBlock *pbn = pb->next;
1621 pb->next = the_pFile->pbHead;
1622 the_pFile->pbHead->prev = pb;
1623 the_pFile->pbHead = pb;
1626 pb->prev->next = pbn;
1628 // If the pBlock that we just moved was the last
1629 // one in the link of all of the pBlocks, then we
1630 // need to point the tail to the block just before
1631 // the one we moved.
1632 // Note: if pb->next is NULL, then pb must have
1633 // been the last pBlock in the chain.
1636 pbn->prev = pb->prev;
1638 the_pFile->pbTail = pb->prev;
1649 void copypCode(FILE *of, char dbName)
1653 if(!of || !the_pFile)
1656 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1657 if(getpBlock_dbName(pb) == dbName) {
1666 void resetpCodeStatistics (void)
1668 pcode_insns = pcode_doubles = 0;
1671 void dumppCodeStatistics (FILE *of)
1673 /* dump statistics */
1675 fprintf (of, ";\tcode size estimation:\n");
1676 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1680 void pcode_test(void)
1683 DFPRINTF((stderr,"pcode is alive!\n"));
1693 /* create the file name */
1694 strcpy(buffer,dstFileName);
1695 strcat(buffer,".p");
1697 if( !(pFile = fopen(buffer, "w" ))) {
1698 werror(E_FILE_OPEN_ERR,buffer);
1702 fprintf(pFile,"pcode dump\n\n");
1704 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1705 fprintf(pFile,"\n\tNew pBlock\n\n");
1707 fprintf(pFile,"%s",pb->cmemmap->sname);
1709 fprintf(pFile,"internal pblock");
1711 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1712 printpBlock(pFile,pb);
1716 /*-----------------------------------------------------------------*/
1717 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1718 /* ister, RegCond will return the bit being referenced. */
1720 /* fixme - why not just OR in the pcop bit field */
1721 /*-----------------------------------------------------------------*/
1723 static int RegCond(pCodeOp *pcop)
1729 if (pcop->type == PO_GPR_BIT) {
1730 char *name = pcop->name;
1732 name = PCOR(pcop)->r->name;
1733 if (strcmp(name, pc_status.pcop.name) == 0)
1735 switch(PCORB(pcop)->bit) {
1749 /*-----------------------------------------------------------------*/
1750 /* newpCode - create and return a newly initialized pCode */
1752 /* fixme - rename this */
1754 /* The purpose of this routine is to create a new Instruction */
1755 /* pCode. This is called by gen.c while the assembly code is being */
1759 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1760 /* (note that the op is analogous to but not the */
1761 /* same thing as the opcode of the instruction.) */
1762 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1765 /* a pointer to the new malloc'd pCode is returned. */
1769 /*-----------------------------------------------------------------*/
1770 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1772 pCodeInstruction *pci ;
1774 if(!mnemonics_initialized)
1775 pic14initMnemonics();
1777 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1779 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1780 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1781 pci->pc.id = PCodeID();
1784 if(pci->inCond & PCC_EXAMINE_PCOP)
1785 pci->inCond |= RegCond(pcop);
1787 if(pci->outCond & PCC_EXAMINE_PCOP)
1788 pci->outCond |= RegCond(pcop);
1790 pci->pc.prev = pci->pc.next = NULL;
1791 return (pCode *)pci;
1794 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1800 /*-----------------------------------------------------------------*/
1801 /* newpCodeWild - create a "wild" as in wild card pCode */
1803 /* Wild pcodes are used during the peep hole optimizer to serve */
1804 /* as place holders for any instruction. When a snippet of code is */
1805 /* compared to a peep hole rule, the wild card opcode will match */
1806 /* any instruction. However, the optional operand and label are */
1807 /* additional qualifiers that must also be matched before the */
1808 /* line (of assembly code) is declared matched. Note that the */
1809 /* operand may be wild too. */
1811 /* Note, a wild instruction is specified just like a wild var: */
1812 /* %4 ; A wild instruction, */
1813 /* See the peeph.def file for additional examples */
1815 /*-----------------------------------------------------------------*/
1817 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1822 pcw = Safe_calloc(1,sizeof(pCodeWild));
1824 pcw->pci.pc.type = PC_WILD;
1825 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1826 pcw->id = PCodeID();
1827 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1828 pcw->pci.pc.pb = NULL;
1830 // pcw->pci.pc.analyze = genericAnalyze;
1831 pcw->pci.pc.destruct = genericDestruct;
1832 pcw->pci.pc.print = genericPrint;
1834 pcw->id = pCodeID; // this is the 'n' in %n
1835 pcw->operand = optional_operand;
1836 pcw->label = optional_label;
1838 pcw->mustBeBitSkipInst = 0;
1839 pcw->mustNotBeBitSkipInst = 0;
1840 pcw->invertBitSkipInst = 0;
1842 return ( (pCode *)pcw);
1846 /*-----------------------------------------------------------------*/
1847 /* newPcodeInlineP - create a new pCode from a char string */
1848 /*-----------------------------------------------------------------*/
1851 pCode *newpCodeInlineP(char *cP)
1856 pcc = Safe_calloc(1,sizeof(pCodeComment));
1858 pcc->pc.type = PC_INLINE;
1859 pcc->pc.prev = pcc->pc.next = NULL;
1860 pcc->pc.id = PCodeID();
1861 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1864 // pcc->pc.analyze = genericAnalyze;
1865 pcc->pc.destruct = genericDestruct;
1866 pcc->pc.print = genericPrint;
1869 pcc->comment = Safe_strdup(cP);
1871 pcc->comment = NULL;
1873 return ( (pCode *)pcc);
1877 /*-----------------------------------------------------------------*/
1878 /* newPcodeCharP - create a new pCode from a char string */
1879 /*-----------------------------------------------------------------*/
1881 pCode *newpCodeCharP(char *cP)
1886 pcc = Safe_calloc(1,sizeof(pCodeComment));
1888 pcc->pc.type = PC_COMMENT;
1889 pcc->pc.prev = pcc->pc.next = NULL;
1890 pcc->pc.id = PCodeID();
1891 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1894 // pcc->pc.analyze = genericAnalyze;
1895 pcc->pc.destruct = genericDestruct;
1896 pcc->pc.print = genericPrint;
1899 pcc->comment = Safe_strdup(cP);
1901 pcc->comment = NULL;
1903 return ( (pCode *)pcc);
1907 /*-----------------------------------------------------------------*/
1908 /* newpCodeFunction - */
1909 /*-----------------------------------------------------------------*/
1912 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1916 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1917 //_ALLOC(pcf,sizeof(pCodeFunction));
1919 pcf->pc.type = PC_FUNCTION;
1920 pcf->pc.prev = pcf->pc.next = NULL;
1921 pcf->pc.id = PCodeID();
1922 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1925 // pcf->pc.analyze = genericAnalyze;
1926 pcf->pc.destruct = genericDestruct;
1927 pcf->pc.print = pCodePrintFunction;
1932 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1933 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1934 strcpy(pcf->modname,mod);
1936 pcf->modname = NULL;
1939 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1940 pcf->fname = Safe_calloc(1,strlen(f)+1);
1941 strcpy(pcf->fname,f);
1945 pcf->isPublic = (unsigned)isPublic;
1947 return ( (pCode *)pcf);
1951 /*-----------------------------------------------------------------*/
1953 /*-----------------------------------------------------------------*/
1954 void destructpCodeFlow(pCode *pc)
1956 if(!pc || !isPCFL(pc))
1965 deleteSet(&PCFL(pc)->registers);
1966 deleteSet(&PCFL(pc)->from);
1967 deleteSet(&PCFL(pc)->to);
1972 pCode *newpCodeFlow(void )
1976 //_ALLOC(pcflow,sizeof(pCodeFlow));
1977 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1979 pcflow->pc.type = PC_FLOW;
1980 pcflow->pc.prev = pcflow->pc.next = NULL;
1981 pcflow->pc.pb = NULL;
1983 // pcflow->pc.analyze = genericAnalyze;
1984 pcflow->pc.destruct = destructpCodeFlow;
1985 pcflow->pc.print = genericPrint;
1987 pcflow->pc.seq = GpcFlowSeq++;
1989 pcflow->from = pcflow->to = NULL;
1991 pcflow->inCond = PCC_NONE;
1992 pcflow->outCond = PCC_NONE;
1994 pcflow->firstBank = 'U'; /* Undetermined */
1995 pcflow->lastBank = 'U'; /* Undetermined */
1997 pcflow->FromConflicts = 0;
1998 pcflow->ToConflicts = 0;
2002 pcflow->registers = newSet();
2004 return ( (pCode *)pcflow);
2008 /*-----------------------------------------------------------------*/
2009 /*-----------------------------------------------------------------*/
2010 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2012 pCodeFlowLink *pcflowLink;
2014 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2016 pcflowLink->pcflow = pcflow;
2017 pcflowLink->bank_conflict = 0;
2022 /*-----------------------------------------------------------------*/
2023 /* newpCodeCSource - create a new pCode Source Symbol */
2024 /*-----------------------------------------------------------------*/
2026 pCode *newpCodeCSource(int ln, char *f, const char *l)
2031 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2033 pccs->pc.type = PC_CSOURCE;
2034 pccs->pc.prev = pccs->pc.next = NULL;
2035 pccs->pc.id = PCodeID();
2038 pccs->pc.destruct = genericDestruct;
2039 pccs->pc.print = genericPrint;
2041 pccs->line_number = ln;
2043 pccs->line = Safe_strdup(l);
2048 pccs->file_name = Safe_strdup(f);
2050 pccs->file_name = NULL;
2052 return ( (pCode *)pccs);
2056 /*******************************************************************/
2057 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2058 /* added by VR 6-Jun-2003 */
2059 /*******************************************************************/
2061 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2068 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2069 pcad->pci.pc.type = PC_ASMDIR;
2070 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2071 pcad->pci.pc.pb = NULL;
2072 pcad->pci.pc.destruct = genericDestruct;
2073 pcad->pci.pc.print = genericPrint;
2075 if(asdir && *asdir) {
2077 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2079 pcad->directive = Safe_strdup( asdir );
2082 va_start(ap, argfmt);
2084 memset(buffer, 0, sizeof(buffer));
2085 if(argfmt && *argfmt)
2086 vsprintf(buffer, argfmt, ap);
2090 while(isspace((unsigned char)*lbp))lbp++;
2093 pcad->arg = Safe_strdup( lbp );
2095 return ((pCode *)pcad);
2098 /*-----------------------------------------------------------------*/
2099 /* pCodeLabelDestruct - free memory used by a label. */
2100 /*-----------------------------------------------------------------*/
2101 static void pCodeLabelDestruct(pCode *pc)
2107 if((pc->type == PC_LABEL) && PCL(pc)->label)
2108 free(PCL(pc)->label);
2114 pCode *newpCodeLabel(char *name, int key)
2120 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2122 pcl->pc.type = PC_LABEL;
2123 pcl->pc.prev = pcl->pc.next = NULL;
2124 pcl->pc.id = PCodeID();
2125 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2128 // pcl->pc.analyze = genericAnalyze;
2129 pcl->pc.destruct = pCodeLabelDestruct;
2130 pcl->pc.print = pCodePrintLabel;
2136 sprintf(s,"_%05d_DS_",key);
2141 pcl->label = Safe_strdup(s);
2143 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2144 return ( (pCode *)pcl);
2149 /*-----------------------------------------------------------------*/
2150 /* newpBlock - create and return a pointer to a new pBlock */
2151 /*-----------------------------------------------------------------*/
2152 pBlock *newpBlock(void)
2157 PpB = Safe_calloc(1,sizeof(pBlock) );
2158 PpB->next = PpB->prev = NULL;
2160 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2161 PpB->tregisters = NULL;
2163 PpB->FlowTree = NULL;
2169 /*-----------------------------------------------------------------*/
2170 /* newpCodeChain - create a new chain of pCodes */
2171 /*-----------------------------------------------------------------*
2173 * This function will create a new pBlock and the pointer to the
2174 * pCode that is passed in will be the first pCode in the block.
2175 *-----------------------------------------------------------------*/
2178 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2181 pBlock *pB = newpBlock();
2183 pB->pcHead = pB->pcTail = pc;
2190 /*-----------------------------------------------------------------*/
2191 /* newpCodeOpLabel - Create a new label given the key */
2192 /* Note, a negative key means that the label is part of wild card */
2193 /* (and hence a wild card label) used in the pCodePeep */
2194 /* optimizations). */
2195 /*-----------------------------------------------------------------*/
2197 pCodeOp *newpCodeOpLabel(char *name, int key)
2200 static int label_key=-1;
2204 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2205 pcop->type = PO_LABEL;
2210 sprintf(s=buffer,"_%05d_DS_",key);
2212 s = name, key = label_key--;
2214 PCOLAB(pcop)->offset = 0;
2216 pcop->name = Safe_strdup(s);
2218 ((pCodeOpLabel *)pcop)->key = key;
2220 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2224 /*-----------------------------------------------------------------*/
2225 /*-----------------------------------------------------------------*/
2226 pCodeOp *newpCodeOpLit(int lit)
2232 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2233 pcop->type = PO_LITERAL;
2237 sprintf(s,"0x%02x", (unsigned char)lit);
2239 pcop->name = Safe_strdup(s);
2242 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2247 /*-----------------------------------------------------------------*/
2248 /*-----------------------------------------------------------------*/
2249 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2253 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2254 pcop->type = PO_IMMEDIATE;
2257 pcop->name = Safe_strdup(name);
2260 r = dirregWithName(name);
2264 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2265 PCOI(pcop)->rIdx = r->rIdx;
2267 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2268 PCOI(pcop)->rIdx = -1;
2270 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2275 PCOI(pcop)->index = index;
2276 PCOI(pcop)->offset = offset;
2277 PCOI(pcop)->_const = code_space;
2278 PCOI(pcop)->_function = is_func;
2283 /*-----------------------------------------------------------------*/
2284 /*-----------------------------------------------------------------*/
2285 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2291 if(!pcwb || !subtype) {
2292 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2296 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2297 pcop->type = PO_WILD;
2298 sprintf(s,"%%%d",id);
2299 pcop->name = Safe_strdup(s);
2301 PCOW(pcop)->id = id;
2302 PCOW(pcop)->pcwb = pcwb;
2303 PCOW(pcop)->subtype = subtype;
2304 PCOW(pcop)->matched = NULL;
2308 /*-----------------------------------------------------------------*/
2309 /* Find a symbol with matching name */
2310 /*-----------------------------------------------------------------*/
2311 static symbol *symFindWithName(memmap * map, const char *name)
2315 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2316 if (sym->rname && (strcmp(sym->rname,name)==0))
2322 /*-----------------------------------------------------------------*/
2323 /*-----------------------------------------------------------------*/
2324 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2329 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2330 pcop->type = PO_GPR_BIT;
2332 PCORB(pcop)->bit = ibit;
2333 PCORB(pcop)->inBitSpace = inBitSpace;
2335 if (name) r = regFindWithName(name);
2337 // Register has not been allocated - check for symbol information
2339 sym = symFindWithName(bit, name);
2340 if (!sym) sym = symFindWithName(sfrbit, name);
2341 if (!sym) sym = symFindWithName(sfr, name);
2343 r = allocNewDirReg(sym->etype,name);
2349 PCOR(pcop)->rIdx = r->rIdx;
2351 pcop->name = Safe_strdup(name);
2352 PCOR(pcop)->r = NULL;
2353 PCOR(pcop)->rIdx = 0;
2358 /*-----------------------------------------------------------------*
2359 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2361 * If rIdx >=0 then a specific register from the set of registers
2362 * will be selected. If rIdx <0, then a new register will be searched
2364 *-----------------------------------------------------------------*/
2366 pCodeOp *newpCodeOpReg(int rIdx)
2370 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2375 PCOR(pcop)->rIdx = rIdx;
2376 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2378 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2381 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2385 pcop->type = PCOR(pcop)->r->pc_type;
2390 pCodeOp *newpCodeOpRegFromStr(char *name)
2394 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2395 PCOR(pcop)->r = allocRegByName(name, 1);
2396 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2397 pcop->type = PCOR(pcop)->r->pc_type;
2398 pcop->name = PCOR(pcop)->r->name;
2403 pCodeOp *newpCodeOpStr(char *name)
2407 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2408 pcop->type = PO_STR;
2409 pcop->name = Safe_strdup(name);
2411 PCOS(pcop)->isPublic = 0;
2417 /*-----------------------------------------------------------------*/
2418 /*-----------------------------------------------------------------*/
2420 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2427 pcop = newpCodeOpBit(name, -1,0);
2431 pcop = newpCodeOpLit(-1);
2435 pcop = newpCodeOpLabel(NULL,-1);
2439 pcop = newpCodeOpReg(-1);
2442 case PO_GPR_POINTER:
2443 case PO_GPR_REGISTER:
2445 pcop = newpCodeOpRegFromStr(name);
2447 pcop = newpCodeOpReg(-1);
2451 pcop = newpCodeOpStr(name);
2455 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2458 pcop->name = Safe_strdup(name);
2466 /*-----------------------------------------------------------------*/
2467 /*-----------------------------------------------------------------*/
2468 void pCodeConstString(char *name, char *value)
2473 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2478 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2482 sprintf(buffer,"; %s = %s",name,value);
2483 for (i=strlen(buffer); i--; ) {
2484 unsigned char c = buffer[i];
2485 if (c=='\r' || c=='\n') {
2486 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2488 if (c=='\r') buffer[i+1] = 'r';
2489 else if (c=='\n') buffer[i+1] = 'n';
2493 addpCode2pBlock(pb,newpCodeCharP(buffer));
2494 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2497 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2503 /*-----------------------------------------------------------------*/
2504 /*-----------------------------------------------------------------*/
2505 void pCodeReadCodeTable(void)
2509 fprintf(stderr, " %s\n",__FUNCTION__);
2511 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2515 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2516 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2517 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2518 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2520 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2521 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2522 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2523 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2528 /*-----------------------------------------------------------------*/
2529 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2530 /*-----------------------------------------------------------------*/
2531 void addpCode2pBlock(pBlock *pb, pCode *pc)
2538 /* If this is the first pcode to be added to a block that
2539 * was initialized with a NULL pcode, then go ahead and
2540 * make this pcode the head and tail */
2541 pb->pcHead = pb->pcTail = pc;
2544 pb->pcTail->next = pc;
2546 pc->prev = pb->pcTail;
2553 /*-----------------------------------------------------------------*/
2554 /* addpBlock - place a pBlock into the pFile */
2555 /*-----------------------------------------------------------------*/
2556 void addpBlock(pBlock *pb)
2558 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2561 /* First time called, we'll pass through here. */
2562 //_ALLOC(the_pFile,sizeof(pFile));
2563 the_pFile = Safe_calloc(1,sizeof(pFile));
2564 the_pFile->pbHead = the_pFile->pbTail = pb;
2565 the_pFile->functions = NULL;
2569 the_pFile->pbTail->next = pb;
2570 pb->prev = the_pFile->pbTail;
2572 the_pFile->pbTail = pb;
2575 /*-----------------------------------------------------------------*/
2576 /* removepBlock - remove a pBlock from the pFile */
2577 /*-----------------------------------------------------------------*/
2578 void removepBlock(pBlock *pb)
2586 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2588 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2591 if(pbs == the_pFile->pbHead)
2592 the_pFile->pbHead = pbs->next;
2594 if (pbs == the_pFile->pbTail)
2595 the_pFile->pbTail = pbs->prev;
2598 pbs->next->prev = pbs->prev;
2601 pbs->prev->next = pbs->next;
2608 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2612 /*-----------------------------------------------------------------*/
2613 /* printpCode - write the contents of a pCode to a file */
2614 /*-----------------------------------------------------------------*/
2615 void printpCode(FILE *of, pCode *pc)
2626 fprintf(of,"warning - unable to print pCode\n");
2629 /*-----------------------------------------------------------------*/
2630 /* printpBlock - write the contents of a pBlock to a file */
2631 /*-----------------------------------------------------------------*/
2632 void printpBlock(FILE *of, pBlock *pb)
2642 for(pc = pb->pcHead; pc; pc = pc->next) {
2647 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2657 /*-----------------------------------------------------------------*/
2659 /* pCode processing */
2663 /*-----------------------------------------------------------------*/
2665 void unlinkpCode(pCode *pc)
2671 fprintf(stderr,"Unlinking: ");
2672 printpCode(stderr, pc);
2675 pc->prev->next = pc->next;
2677 pc->next->prev = pc->prev;
2680 /* RN: I believe this should be right here, but this did not
2681 * cure the bug I was hunting... */
2682 /* must keep labels -- attach to following instruction */
2683 if (isPCI(pc) && PCI(pc)->label && pc->next)
2685 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2688 pBranchAppend (pcnext->label, PCI(pc)->label);
2692 pc->prev = pc->next = NULL;
2696 /*-----------------------------------------------------------------*/
2697 /*-----------------------------------------------------------------*/
2699 static void genericDestruct(pCode *pc)
2705 /* For instructions, tell the register (if there's one used)
2706 * that it's no longer needed */
2707 regs *reg = getRegFromInstruction(pc);
2709 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2712 /* Instead of deleting the memory used by this pCode, mark
2713 * the object as bad so that if there's a pointer to this pCode
2714 * dangling around somewhere then (hopefully) when the type is
2715 * checked we'll catch it.
2720 addpCode2pBlock(pb_dead_pcodes, pc);
2727 /*-----------------------------------------------------------------*/
2728 /* Copies the pCodeInstruction flow pointer from source pCode */
2729 /*-----------------------------------------------------------------*/
2730 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2732 pCodeFlow *pcflow = 0;
2733 for (p=pcs; p; p=p->prev) {
2735 pcflow = PCI(p)->pcflow;
2739 pcflow = (pCodeFlow*)p;
2743 PCI(pcd)->pcflow = pcflow;
2746 /*-----------------------------------------------------------------*/
2747 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2748 /* into the pCode chain containing pc1 */
2749 /*-----------------------------------------------------------------*/
2750 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2756 pc2->next = pc1->next;
2758 pc1->next->prev = pc2;
2764 /* If this is an instrution type propogate the flow */
2766 CopyFlow(PCI(pc2),pc1);
2769 /*------------------------------------------------------------------*/
2770 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2771 /* into the pCode chain containing pc1 */
2772 /*------------------------------------------------------------------*/
2773 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2779 pc2->prev = pc1->prev;
2781 pc1->prev->next = pc2;
2787 /* If this is an instrution type propogate the flow */
2789 CopyFlow(PCI(pc2),pc1);
2792 /*-----------------------------------------------------------------*/
2793 /* pCodeOpCopy - copy a pcode operator */
2794 /*-----------------------------------------------------------------*/
2795 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2797 pCodeOp *pcopnew=NULL;
2802 switch(pcop->type) {
2805 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2806 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2814 case PO_GPR_REGISTER:
2816 case PO_GPR_POINTER:
2817 case PO_SFR_REGISTER:
2821 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2822 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2823 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2824 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2828 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2829 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2830 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2834 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2835 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2841 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2842 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2843 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2847 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2848 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2849 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2853 /* Here we expand the wild card into the appropriate type: */
2854 /* By recursively calling pCodeOpCopy */
2855 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2856 if(PCOW(pcop)->matched)
2857 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2860 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2861 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2862 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2869 assert ( !"unhandled pCodeOp type copied" );
2874 pcopnew->name = Safe_strdup(pcop->name);
2876 pcopnew->name = NULL;
2881 /*-----------------------------------------------------------------*/
2882 /* popCopyReg - copy a pcode operator */
2883 /*-----------------------------------------------------------------*/
2884 pCodeOp *popCopyReg(pCodeOpReg *pc)
2888 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2889 pcor->pcop.type = pc->pcop.type;
2891 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2892 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2894 pcor->pcop.name = NULL;
2896 if (pcor->pcop.type == PO_IMMEDIATE){
2897 PCOL(pcor)->lit = PCOL(pc)->lit;
2900 pcor->rIdx = pc->rIdx;
2904 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2909 /*-----------------------------------------------------------------*/
2910 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2911 /*-----------------------------------------------------------------*/
2912 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2914 pCodeInstruction *new_pci;
2917 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2919 new_pci = PCI(newpCode(pci->op,pci->pcop));
2921 new_pci->pc.pb = pci->pc.pb;
2922 new_pci->from = pci->from;
2923 new_pci->to = pci->to;
2924 new_pci->label = pci->label;
2925 new_pci->pcflow = pci->pcflow;
2927 return PCODE(new_pci);
2930 /*-----------------------------------------------------------------*/
2931 /*-----------------------------------------------------------------*/
2932 void pCodeDeleteChain(pCode *f,pCode *t)
2937 DFPRINTF((stderr,"delete pCode:\n"));
2939 //f->print(stderr,f);
2940 //f->delete(f); this dumps core...
2945 /*-----------------------------------------------------------------*/
2946 /*-----------------------------------------------------------------*/
2947 void pBlockRegs(FILE *of, pBlock *pb)
2952 r = setFirstItem(pb->tregisters);
2954 r = setNextItem(pb->tregisters);
2959 /*-----------------------------------------------------------------*/
2960 /*-----------------------------------------------------------------*/
2961 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2966 int use_buffer = 1; // copy the string to the passed buffer pointer
2971 use_buffer = 0; // Don't bother copying the string to the buffer.
2975 switch(pcop->type) {
2979 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2982 //return PCOR(pcop)->r->name;
2986 if (PCOR(pcop)->r->type == REG_STK)
2987 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2989 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2992 SAFE_snprintf(&buffer,&size,"%s",r->name);
3001 if(PCOI(pcop)->_const) {
3003 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3004 switch(PCOI(pcop)->offset) {
3006 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3009 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3012 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3013 assert ( !"offset too large" );
3014 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3017 8 * PCOI(pcop)->offset );
3020 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3022 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3023 SAFE_snprintf(&s,&size,"(%s + %d)",
3027 switch(PCOI(pcop)->offset) {
3029 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3032 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3035 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3036 assert ( !"offset too large" );
3037 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3047 //size = sizeof(buffer);
3048 if( PCOR(pcop)->instance) {
3049 SAFE_snprintf(&s,&size,"(%s + %d)",
3051 PCOR(pcop)->instance );
3052 //fprintf(stderr,"PO_DIR %s\n",buffer);
3054 SAFE_snprintf(&s,&size,"%s",pcop->name);
3060 if(PCOLAB(pcop)->offset == 1)
3061 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3063 SAFE_snprintf(&s,&size,"%s",pcop->name);
3070 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3073 return PCOR(pcop)->r->name;
3076 /* fall through to the default case */
3080 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3088 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3089 __FILE__, __LINE__, __FUNCTION__,
3092 return "NO operand";
3096 /*-----------------------------------------------------------------*/
3097 /*-----------------------------------------------------------------*/
3098 static char *get_op_from_instruction( pCodeInstruction *pcc)
3102 return get_op(pcc->pcop,NULL,0);
3104 return ("ERROR Null: get_op_from_instruction");
3108 /*-----------------------------------------------------------------*/
3109 /*-----------------------------------------------------------------*/
3110 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3112 fprintf(of,"pcodeopprint- not implemented\n");
3115 /*-----------------------------------------------------------------*/
3116 /* pCode2str - convert a pCode instruction to string */
3117 /*-----------------------------------------------------------------*/
3118 char *pCode2str(char *str, size_t size, pCode *pc)
3126 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3128 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3130 if(PCI(pc)->isBitInst) {
3131 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3132 char *name = PCI(pc)->pcop->name;
3134 name = PCOR(PCI(pc)->pcop)->r->name;
3135 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3136 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3138 SAFE_snprintf(&s,&size,"%s,%d", name,
3139 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3140 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3141 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3143 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3144 //PCI(pc)->pcop->t.bit );
3146 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3147 if( PCI(pc)->num_ops == 2)
3148 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3150 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3152 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3153 if( PCI(pc)->num_ops == 2)
3154 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3161 /* assuming that comment ends with a \n */
3162 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3166 /* assuming that inline code ends with a \n */
3167 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3171 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3174 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3177 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3180 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3183 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3184 SAFE_snprintf(&s,&size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3187 if(PCAD(pc)->directive) {
3188 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3189 } else if(PCAD(pc)->arg) {
3190 /* special case to handle inline labels without a tab */
3191 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3196 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3202 /*-----------------------------------------------------------------*/
3203 /* genericPrint - the contents of a pCode to a file */
3204 /*-----------------------------------------------------------------*/
3205 static void genericPrint(FILE *of, pCode *pc)
3212 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3216 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3220 // If the opcode has a label, print that first
3223 pCodeInstruction *pci = PCI(pc);
3224 pBranch *pbl = pci->label;
3225 while(pbl && pbl->pc) {
3226 if(pbl->pc->type == PC_LABEL)
3227 pCodePrintLabel(of, pbl->pc);
3232 genericPrint(of,PCODE(pci->cline));
3235 pCode2str(str, 256, pc);
3237 fprintf(of,"%s",str);
3241 pCodeOpReg *pcor = PCOR(pci->pcop);
3242 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3244 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3245 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3246 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3251 pBranch *dpb = pc->to; // debug
3253 switch ( dpb->pc->type) {
3255 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3258 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3261 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3264 fprintf(of, "\t;flow");
3278 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3279 if(PCW(pc)->pci.label)
3280 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3282 if(PCW(pc)->operand) {
3283 fprintf(of,";\toperand ");
3284 pCodeOpPrint(of,PCW(pc)->operand );
3290 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3291 if(PCFL(pc)->ancestor)
3292 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3294 fprintf(of,"; from: ");
3296 pCodeFlowLink *link;
3297 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3299 fprintf(of,"%03x ",link->pcflow->pc.seq);
3302 fprintf(of,"; to: ");
3304 pCodeFlowLink *link;
3305 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3307 fprintf(of,"%03x ",link->pcflow->pc.seq);
3315 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3316 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3321 pBranch *pbl = PCAD(pc)->pci.label;
3322 while(pbl && pbl->pc) {
3323 if(pbl->pc->type == PC_LABEL)
3324 pCodePrintLabel(of, pbl->pc);
3328 if(PCAD(pc)->directive) {
3329 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3332 /* special case to handle inline labels without tab */
3333 fprintf(of, "%s\n", PCAD(pc)->arg);
3339 fprintf(of,"unknown pCode type %d\n",pc->type);
3343 /*-----------------------------------------------------------------*/
3344 /* pCodePrintFunction - prints function begin/end */
3345 /*-----------------------------------------------------------------*/
3347 static void pCodePrintFunction(FILE *of, pCode *pc)
3353 if( ((pCodeFunction *)pc)->modname)
3354 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3356 if(PCF(pc)->fname) {
3357 pBranch *exits = PCF(pc)->to;
3359 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3362 exits = exits->next;
3365 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3368 if((PCF(pc)->from &&
3369 PCF(pc)->from->pc->type == PC_FUNCTION &&
3370 PCF(PCF(pc)->from->pc)->fname) )
3371 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3373 fprintf(of,"; exit point [can't find entry point]\n");
3376 /*-----------------------------------------------------------------*/
3377 /* pCodePrintLabel - prints label */
3378 /*-----------------------------------------------------------------*/
3380 static void pCodePrintLabel(FILE *of, pCode *pc)
3387 fprintf(of,"%s\n",PCL(pc)->label);
3388 else if (PCL(pc)->key >=0)
3389 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3391 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3395 /*-----------------------------------------------------------------*/
3396 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3397 /* remove it if it is found. */
3398 /*-----------------------------------------------------------------*/
3399 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3405 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3406 b = PCI(pcl)->label;
3408 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3412 //fprintf (stderr, "%s \n",__FUNCTION__);
3413 //pcl->print(stderr,pcl);
3414 //pc->print(stderr,pc);
3417 //fprintf (stderr, "found label\n");
3421 bprev->next = b->next; /* Not first pCode in chain */
3425 PCI(pcl)->label = b->next; /* First pCode in chain */
3428 return; /* A label can't occur more than once */
3435 /*-----------------------------------------------------------------*/
3436 /*-----------------------------------------------------------------*/
3437 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3456 /*-----------------------------------------------------------------*/
3457 /* pBranchLink - given two pcodes, this function will link them */
3458 /* together through their pBranches */
3459 /*-----------------------------------------------------------------*/
3460 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3464 // Declare a new branch object for the 'from' pCode.
3466 //_ALLOC(b,sizeof(pBranch));
3467 b = Safe_calloc(1,sizeof(pBranch));
3468 b->pc = PCODE(t); // The link to the 'to' pCode.
3471 f->to = pBranchAppend(f->to,b);
3473 // Now do the same for the 'to' pCode.
3475 //_ALLOC(b,sizeof(pBranch));
3476 b = Safe_calloc(1,sizeof(pBranch));
3480 t->from = pBranchAppend(t->from,b);
3485 /*-----------------------------------------------------------------*/
3486 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3488 /*-----------------------------------------------------------------*/
3489 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3502 /*-----------------------------------------------------------------*/
3503 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3504 /*-----------------------------------------------------------------*/
3505 static void pCodeUnlink(pCode *pc)
3510 if(!pc->prev || !pc->next) {
3511 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3515 /* first remove the pCode from the chain */
3516 pc->prev->next = pc->next;
3517 pc->next->prev = pc->prev;
3519 /* Now for the hard part... */
3521 /* Remove the branches */
3525 pc1 = pb1->pc; /* Get the pCode that branches to the
3526 * one we're unlinking */
3528 /* search for the link back to this pCode (the one we're
3530 if(pb2 = pBranchFind(pc1->to,pc)) {
3531 pb2->pc = pc->to->pc; // make the replacement
3533 /* if the pCode we're unlinking contains multiple 'to'
3534 * branches (e.g. this a skip instruction) then we need
3535 * to copy these extra branches to the chain. */
3537 pBranchAppend(pb2, pc->to->next);
3546 /*-----------------------------------------------------------------*/
3547 /*-----------------------------------------------------------------*/
3549 static void genericAnalyze(pCode *pc)
3559 // Go through the pCodes that are in pCode chain and link
3560 // them together through the pBranches. Note, the pCodes
3561 // are linked together as a contiguous stream like the
3562 // assembly source code lines. The linking here mimics this
3563 // except that comments are not linked in.
3565 pCode *npc = pc->next;
3567 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3568 pBranchLink(pc,npc);
3573 /* reached the end of the pcode chain without finding
3574 * an instruction we could link to. */
3578 fprintf(stderr,"analyze PC_FLOW\n");
3582 fprintf(stderr,";A bad pCode is being used\n");
3588 /*-----------------------------------------------------------------*/
3589 /*-----------------------------------------------------------------*/
3590 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3594 if(pc->type == PC_LABEL) {
3595 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3598 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3599 pbr = PCI(pc)->label;
3601 if(pbr->pc->type == PC_LABEL) {
3602 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3612 /*-----------------------------------------------------------------*/
3613 /*-----------------------------------------------------------------*/
3614 int checkLabel(pCode *pc)
3618 if(pc && isPCI(pc)) {
3619 pbr = PCI(pc)->label;
3621 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3631 /*-----------------------------------------------------------------*/
3632 /* findLabelinpBlock - Search the pCode for a particular label */
3633 /*-----------------------------------------------------------------*/
3634 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3641 for(pc = pb->pcHead; pc; pc = pc->next)
3642 if(compareLabel(pc,pcop_label))
3648 /*-----------------------------------------------------------------*/
3649 /* findLabel - Search the pCode for a particular label */
3650 /*-----------------------------------------------------------------*/
3651 pCode * findLabel(pCodeOpLabel *pcop_label)
3659 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3660 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3664 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3668 /*-----------------------------------------------------------------*/
3669 /* findNextpCode - given a pCode, find the next of type 'pct' */
3670 /* in the linked list */
3671 /*-----------------------------------------------------------------*/
3672 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3685 /*-----------------------------------------------------------------*/
3686 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3687 /* in the linked list */
3688 /*-----------------------------------------------------------------*/
3689 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3693 if(pc->type == pct) {
3695 static unsigned int stop;
3697 stop++; // Place break point here
3708 /*-----------------------------------------------------------------*/
3709 /* findNextInstruction - given a pCode, find the next instruction */
3710 /* in the linked list */
3711 /*-----------------------------------------------------------------*/
3712 pCode * findNextInstruction(pCode *pci)
3717 if((pc->type == PC_OPCODE)
3718 || (pc->type == PC_WILD)
3719 || (pc->type == PC_ASMDIR))
3723 fprintf(stderr,"findNextInstruction: ");
3724 printpCode(stderr, pc);
3729 //fprintf(stderr,"Couldn't find instruction\n");
3733 /*-----------------------------------------------------------------*/
3734 /* findNextInstruction - given a pCode, find the next instruction */
3735 /* in the linked list */
3736 /*-----------------------------------------------------------------*/
3737 pCode * findPrevInstruction(pCode *pci)
3743 if((pc->type == PC_OPCODE)
3744 || (pc->type == PC_WILD)
3745 || (pc->type == PC_ASMDIR))
3750 fprintf(stderr,"pic16_findPrevInstruction: ");
3751 printpCode(stderr, pc);
3756 //fprintf(stderr,"Couldn't find instruction\n");
3760 /*-----------------------------------------------------------------*/
3761 /* findFunctionEnd - given a pCode find the end of the function */
3762 /* that contains it */
3763 /*-----------------------------------------------------------------*/
3764 pCode * findFunctionEnd(pCode *pc)
3767 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3773 fprintf(stderr,"Couldn't find function end\n");
3778 /*-----------------------------------------------------------------*/
3779 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3780 /* instruction with which it is associated. */
3781 /*-----------------------------------------------------------------*/
3782 static void AnalyzeLabel(pCode *pc)
3791 static void AnalyzeGOTO(pCode *pc)
3794 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3798 static void AnalyzeSKIP(pCode *pc)
3801 pBranchLink(pc,findNextInstruction(pc->next));
3802 pBranchLink(pc,findNextInstruction(pc->next->next));
3806 static void AnalyzeRETURN(pCode *pc)
3809 // branch_link(pc,findFunctionEnd(pc->next));
3815 /*-----------------------------------------------------------------*/
3816 /*-----------------------------------------------------------------*/
3817 regs * getRegFromInstruction(pCode *pc)
3823 PCI(pc)->num_ops == 0 )
3826 switch(PCI(pc)->pcop->type) {
3833 case PO_SFR_REGISTER:
3836 return PCOR(PCI(pc)->pcop)->r;
3838 case PO_GPR_REGISTER:
3841 r = PCOR(PCI(pc)->pcop)->r;
3844 return dirregWithName(PCI(pc)->pcop->name);
3850 r = PCOI(PCI(pc)->pcop)->r;
3853 return dirregWithName(PCI(pc)->pcop->name);
3863 /*-----------------------------------------------------------------*/
3864 /*-----------------------------------------------------------------*/
3866 void AnalyzepBlock(pBlock *pb)
3873 /* Find all of the registers used in this pBlock
3874 * by looking at each instruction and examining it's
3877 for(pc = pb->pcHead; pc; pc = pc->next) {
3879 /* Is this an instruction with operands? */
3880 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3882 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3883 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3885 /* Loop through all of the registers declared so far in
3886 this block and see if we find this one there */
3888 regs *r = setFirstItem(pb->tregisters);
3891 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3892 PCOR(PCI(pc)->pcop)->r = r;
3895 r = setNextItem(pb->tregisters);
3899 /* register wasn't found */
3900 //r = Safe_calloc(1, sizeof(regs));
3901 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3902 //addSet(&pb->tregisters, r);
3903 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3904 //PCOR(PCI(pc)->pcop)->r = r;
3905 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3907 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3910 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3911 if(PCOR(PCI(pc)->pcop)->r) {
3912 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3913 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3915 if(PCI(pc)->pcop->name)
3916 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3918 fprintf(stderr,"ERROR: NULL register\n");
3927 /*-----------------------------------------------------------------*/
3929 /*-----------------------------------------------------------------*/
3930 void InsertpFlow(pCode *pc, pCode **pflow)
3933 PCFL(*pflow)->end = pc;
3935 if(!pc || !pc->next)
3938 *pflow = newpCodeFlow();
3939 pCodeInsertAfter(pc, *pflow);
3942 /*-----------------------------------------------------------------*/
3943 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3944 /* the flow blocks. */
3946 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3947 * point the instruction flow changes.
3949 /*-----------------------------------------------------------------*/
3950 void BuildFlow(pBlock *pb)
3953 pCode *last_pci=NULL;
3960 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3961 /* Insert a pCodeFlow object at the beginning of a pBlock */
3963 InsertpFlow(pb->pcHead, &pflow);
3965 //pflow = newpCodeFlow(); /* Create a new Flow object */
3966 //pflow->next = pb->pcHead; /* Make the current head the next object */
3967 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3968 //pb->pcHead = pflow; /* Make the Flow object the head */
3971 for( pc = findNextInstruction(pb->pcHead);
3973 pc=findNextInstruction(pc)) {
3976 PCI(pc)->pcflow = PCFL(pflow);
3978 //fprintf(stderr," build: ");
3979 //pc->print(stderr, pc);
3980 //pflow->print(stderr,pflow);
3982 if (checkLabel(pc)) {
3984 /* This instruction marks the beginning of a
3985 * new flow segment */
3990 /* If the previous pCode is not a flow object, then
3991 * insert a new flow object. (This check prevents
3992 * two consecutive flow objects from being insert in
3993 * the case where a skip instruction preceeds an
3994 * instruction containing a label.) */
3996 last_pci = findPrevInstruction (pc->prev);
3998 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3999 InsertpFlow(last_pci, &pflow);
4001 PCI(pc)->pcflow = PCFL(pflow);
4005 if(isPCI_SKIP(pc)) {
4007 /* The two instructions immediately following this one
4008 * mark the beginning of a new flow segment */
4010 while(pc && isPCI_SKIP(pc)) {
4012 PCI(pc)->pcflow = PCFL(pflow);
4016 InsertpFlow(pc, &pflow);
4017 pc=findNextInstruction(pc->next);
4025 PCI(pc)->pcflow = PCFL(pflow);
4027 InsertpFlow(pc, &pflow);
4029 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4031 InsertpFlow(pc, &pflow);
4040 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4042 PCFL(pflow)->end = pb->pcTail;
4045 /*-------------------------------------------------------------------*/
4046 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4047 /* the flow blocks. */
4049 * unBuildFlow removes pCodeFlow objects from a pCode chain
4051 /*-----------------------------------------------------------------*/
4052 void unBuildFlow(pBlock *pb)
4067 if(PCI(pc)->pcflow) {
4068 //free(PCI(pc)->pcflow);
4069 PCI(pc)->pcflow = NULL;
4072 } else if(isPCFL(pc) )
4081 /*-----------------------------------------------------------------*/
4082 /*-----------------------------------------------------------------*/
4083 void dumpCond(int cond)
4086 static char *pcc_str[] = {
4100 int ncond = sizeof(pcc_str) / sizeof(char *);
4103 fprintf(stderr, "0x%04X\n",cond);
4105 for(i=0,j=1; i<ncond; i++, j<<=1)
4107 fprintf(stderr, " %s\n",pcc_str[i]);
4111 /*-----------------------------------------------------------------*/
4112 /*-----------------------------------------------------------------*/
4113 void FlowStats(pCodeFlow *pcflow)
4121 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4123 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4126 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4131 fprintf(stderr, " FlowStats inCond: ");
4132 dumpCond(pcflow->inCond);
4133 fprintf(stderr, " FlowStats outCond: ");
4134 dumpCond(pcflow->outCond);
4138 /*-----------------------------------------------------------------*
4139 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4140 * if it affects the banking bits.
4142 * return: -1 == Banking bits are unaffected by this pCode.
4144 * return: > 0 == Banking bits are affected.
4146 * If the banking bits are affected, then the returned value describes
4147 * which bits are affected and how they're affected. The lower half
4148 * of the integer maps to the bits that are affected, the upper half
4149 * to whether they're set or cleared.
4151 *-----------------------------------------------------------------*/
4153 #define SET_BANK_BIT (1 << 16)
4154 #define CLR_BANK_BIT 0
4156 static int isBankInstruction(pCode *pc)
4164 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4166 // Check to see if the register banks are changing
4167 if(PCI(pc)->isModReg) {
4169 pCodeOp *pcop = PCI(pc)->pcop;
4170 switch(PCI(pc)->op) {
4173 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4174 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4175 return SET_BANK_BIT | PIC_RP0_BIT;
4178 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4179 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4180 return CLR_BANK_BIT | PIC_RP0_BIT;
4185 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4186 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4187 return CLR_BANK_BIT | PIC_RP1_BIT;
4189 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4190 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4191 return CLR_BANK_BIT | PIC_RP1_BIT;
4195 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4196 //genericPrint(stderr, pc);
4207 /*-----------------------------------------------------------------*/
4208 /*-----------------------------------------------------------------*/
4210 static void FillFlow(pCodeFlow *pcflow)
4218 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4220 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4223 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4230 isBankInstruction(pc);
4232 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4235 fprintf(stderr, " FillFlow - Bad end of flow\n");
4237 fprintf(stderr, " FillFlow - Ending flow with\n ");
4238 pc->print(stderr,pc);
4241 fprintf(stderr, " FillFlow inCond: ");
4242 dumpCond(pcflow->inCond);
4243 fprintf(stderr, " FillFlow outCond: ");
4244 dumpCond(pcflow->outCond);
4249 /*-----------------------------------------------------------------*/
4250 /*-----------------------------------------------------------------*/
4251 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4253 pCodeFlowLink *fromLink, *toLink;
4255 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4256 if (from) from->pc.print(stderr, &from->pc);
4257 else fprintf(stderr, "(null)");
4258 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4259 from && from->pcflow ? from->pcflow->pc.seq : 0,
4260 to && to->pcflow ? to->pcflow->pc.seq : 0);
4261 if (to) to->pc.print(stderr, &to->pc);
4262 else fprintf(stderr, "(null)");
4265 if(!from || !to || !to->pcflow || !from->pcflow)
4268 fromLink = newpCodeFlowLink(from->pcflow);
4269 toLink = newpCodeFlowLink(to->pcflow);
4271 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4272 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4276 /*-----------------------------------------------------------------*
4277 * void LinkFlow(pBlock *pb)
4279 * In BuildFlow, the PIC code has been partitioned into contiguous
4280 * non-branching segments. In LinkFlow, we determine the execution
4281 * order of these segments. For example, if one of the segments ends
4282 * with a skip, then we know that there are two possible flow segments
4283 * to which control may be passed.
4284 *-----------------------------------------------------------------*/
4285 void LinkFlow(pBlock *pb)
4291 //fprintf(stderr,"linkflow \n");
4293 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4295 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4298 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4300 //fprintf(stderr," link: ");
4301 //pcflow->print(stderr,pcflow);
4303 //FillFlow(PCFL(pcflow));
4305 /* find last instruction in flow */
4306 pc = findPrevInstruction (PCFL(pcflow)->end);
4308 fprintf(stderr, "%s: flow without end (%u)?\n",
4309 __FUNCTION__, pcflow->seq );
4313 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4314 //pc->print(stderr, pc);
4315 if(isPCI_SKIP(pc)) {
4316 //fprintf(stderr, "ends with skip\n");
4317 //pc->print(stderr,pc);
4318 pct=findNextInstruction(pc->next);
4319 LinkFlow_pCode(PCI(pc),PCI(pct));
4320 pct=findNextInstruction(pct->next);
4321 LinkFlow_pCode(PCI(pc),PCI(pct));
4325 if(isPCI_BRANCH(pc)) {
4326 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4328 //fprintf(stderr, "ends with branch\n ");
4329 //pc->print(stderr,pc);
4331 if(!(pcol && isPCOLAB(pcol))) {
4332 if((PCI(pc)->op != POC_RETLW)
4333 && (PCI(pc)->op != POC_RETURN)
4334 && (PCI(pc)->op != POC_CALL)
4335 && (PCI(pc)->op != POC_RETFIE) )
4337 pc->print(stderr,pc);
4338 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4342 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4343 LinkFlow_pCode(PCI(pc),PCI(pct));
4345 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4346 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4347 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4349 /* link CALLs to next instruction */
4350 if (PCI(pc)->op != POC_CALL) continue;
4354 //fprintf(stderr, "ends with non-branching instruction:\n");
4355 //pc->print(stderr,pc);
4357 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4363 //fprintf(stderr, "ends with unknown\n");
4364 //pc->print(stderr,pc);
4368 fprintf(stderr, "ends with nothing: ERROR\n");
4372 /*-----------------------------------------------------------------*/
4373 /*-----------------------------------------------------------------*/
4375 /*-----------------------------------------------------------------*/
4376 /*-----------------------------------------------------------------*/
4377 int isPCinFlow(pCode *pc, pCode *pcflow)
4383 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4386 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4392 /*-----------------------------------------------------------------*/
4393 /*-----------------------------------------------------------------*/
4395 static void BanksUsedFlow2(pCode *pcflow)
4404 if(!isPCFL(pcflow)) {
4405 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4409 pc = findNextInstruction(pcflow->next);
4411 PCFL(pcflow)->lastBank = -1;
4413 while(isPCinFlow(pc,pcflow)) {
4415 int bank_selected = isBankInstruction(pc);
4417 //if(PCI(pc)->pcflow)
4418 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4420 if(bank_selected > 0) {
4421 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4423 // This instruction is modifying banking bits before accessing registers
4425 PCFL(pcflow)->firstBank = -1;
4427 if(PCFL(pcflow)->lastBank == -1)
4428 PCFL(pcflow)->lastBank = 0;
4430 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4431 if(bank_selected & SET_BANK_BIT)
4432 PCFL(pcflow)->lastBank |= bank;
4436 reg = getRegFromInstruction(pc);
4438 if(reg && !isREGinBank(reg, bank)) {
4439 int allbanks = REGallBanks(reg);
4441 PCFL(pcflow)->firstBank = allbanks;
4443 PCFL(pcflow)->lastBank = allbanks;
4450 pc = findNextInstruction(pc->next);
4453 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4454 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4457 /*-----------------------------------------------------------------*/
4458 /*-----------------------------------------------------------------*/
4460 static void BanksUsedFlow(pBlock *pb)
4465 //pb->pcHead->print(stderr, pb->pcHead);
4467 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4468 //pcflow->print(stderr,pcflow);
4470 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4472 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4474 BanksUsedFlow2(pcflow);
4480 void pCodeReplace (pCode *old, pCode *new)
4482 pCodeInsertAfter (old, new);
4484 /* special handling for pCodeInstructions */
4485 if (isPCI(new) && isPCI(old))
4487 assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4488 PCI(new)->from = PCI(old)->from;
4489 PCI(new)->to = PCI(old)->to;
4490 PCI(new)->label = PCI(old)->label;
4491 PCI(new)->pcflow = PCI(old)->pcflow;
4492 PCI(new)->cline = PCI(old)->cline;
4495 old->destruct (old);
4498 /*-----------------------------------------------------------------*/
4499 /* Inserts a new pCodeInstruction before an existing one */
4500 /*-----------------------------------------------------------------*/
4501 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4505 pcprev = findPrevInstruction(pci->pc.prev);
4507 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4509 /* Move the label, if there is one */
4512 new_pci->label = pci->label;
4516 /* Move the C code comment, if there is one */
4519 new_pci->cline = pci->cline;
4523 /* The new instruction has the same pcflow block */
4524 new_pci->pcflow = pci->pcflow;
4526 /* Arrrrg: is pci's previous instruction is a skip, we need to
4527 * change that into a jump (over pci and the new instruction) ... */
4528 if (pcprev && isPCI_SKIP(pcprev))
4530 symbol *lbl = newiTempLabel (NULL);
4531 pCode *label = newpCodeLabel (NULL, lbl->key);
4532 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4534 pCodeInsertAfter (pcprev, jump);
4536 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4538 pCodeInsertAfter((pCode*)pci, label);
4542 /*-----------------------------------------------------------------*/
4543 /*-----------------------------------------------------------------*/
4544 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4548 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4550 insertPCodeInstruction(pci, PCI(new_pc));
4553 /*-----------------------------------------------------------------*/
4554 /*-----------------------------------------------------------------*/
4555 static void insertBankSel(pCodeInstruction *pci, const char *name)
4559 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4560 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4561 if (pcop->name == 0)
4562 pcop->name = strdup(name);
4563 new_pc = newpCode(POC_BANKSEL, pcop);
4565 insertPCodeInstruction(pci, PCI(new_pc));
4568 /*-----------------------------------------------------------------*/
4569 /* If the register is a fixed known addess then we can assign the */
4570 /* bank selection bits. Otherwise the linker is going to assign */
4571 /* the register location and thus has to set bank selection bits */
4572 /* through the banksel directive. */
4573 /* One critical assumption here is that within this C module all */
4574 /* the locally allocated registers are in the same udata sector. */
4575 /* Therefore banksel is only called for external registers or the */
4576 /* first time a local register is encountered. */
4577 /*-----------------------------------------------------------------*/
4578 static int LastRegIdx = -1; /* If the previous register is the same one again then no need to change bank. */
4579 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4582 int a = reg->alias>>7;
4584 return cur_bank; // This register is available in all banks
4585 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4586 return cur_bank; // This register is available in banks 0 & 1
4588 if (reg->address&0x80) {
4589 if ((cur_bank==1)||(cur_bank==3)) {
4590 return cur_bank; // This register is available in banks 1 & 3
4593 if ((cur_bank==0)||(cur_bank==1)) {
4594 return cur_bank; // This register is available in banks 0 & 2
4600 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4602 LastRegIdx = reg->rIdx;
4606 bank = REG_BANK(reg);
4607 } else if (reg->isExtern) {
4608 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4610 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4612 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.
4613 return 'L'; // Local registers are presumed to be in same linker assigned bank
4614 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4615 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4616 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4617 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4618 } 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
4619 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4620 if (pic14_getMaxRam()&0x100)
4621 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4622 } else { // Current bank and new register banks known - can set bank bits
4623 switch((cur_bank^bank) & 3) {
4627 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4630 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4633 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4634 if (pic14_getMaxRam()&0x100)
4635 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4643 /*-----------------------------------------------------------------*/
4644 /* Check for bank selection pcodes instructions and modify */
4645 /* cur_bank to match. */
4646 /*-----------------------------------------------------------------*/
4647 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4649 if (isSTATUS_REG(reg)) {
4651 if (PCI(pc)->op == POC_BCF) {
4652 int old_bank = *cur_bank;
4653 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4654 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4655 if (*cur_bank & ~(0x3))
4658 *cur_bank = *cur_bank&0x2;
4659 LastRegIdx = reg->rIdx;
4660 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4661 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4662 if (*cur_bank & ~(0x3))
4665 *cur_bank = *cur_bank&0x1;
4666 LastRegIdx = reg->rIdx;
4668 return old_bank != *cur_bank;
4671 if (PCI(pc)->op == POC_BSF) {
4672 int old_bank = *cur_bank;
4673 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4674 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4675 if (*cur_bank & ~(0x3))
4678 *cur_bank = (*cur_bank&0x2) | 0x1;
4679 LastRegIdx = reg->rIdx;
4680 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4681 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4682 if (*cur_bank & ~(0x3))
4685 *cur_bank = (*cur_bank&0x1) | 0x2;
4686 LastRegIdx = reg->rIdx;
4688 return old_bank != *cur_bank;
4691 } else if (PCI(pc)->op == POC_BANKSEL) {
4692 int old_bank = *cur_bank;
4693 regs *r = PCOR(PCI(pc)->pcop)->r;
4694 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4695 LastRegIdx = reg->rIdx;
4696 return old_bank != *cur_bank;
4702 /*-----------------------------------------------------------------*/
4703 /* Set bank selection if necessary */
4704 /*-----------------------------------------------------------------*/
4705 static int DoBankSelect(pCode *pc, int cur_bank) {
4713 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4714 LastRegIdx = -1; /* do not know which register is touched in the called function... */
4715 if (pcf && isPCF(pcf)) {
4717 int rbank = 'U'; // Undetermined
4718 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4719 // Check all the returns to work out what bank is selected
4720 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4722 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4724 rbank = PCI(pcfr)->pcflow->lastBank;
4726 if (rbank != PCI(pcfr)->pcflow->lastBank)
4727 return -1; // Unknown bank - multiple returns with different banks
4732 return -1; // Unknown bank
4734 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4735 /* Extern functions may use registers in different bank - must call banksel */
4736 return -1; /* Unknown bank */
4742 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4743 return -1; /* New bank unknown - linkers choice. */
4746 reg = getRegFromInstruction(pc);
4748 if (IsBankChange(pc,reg,&cur_bank))
4750 if (!isPCI_LIT(pc)) {
4752 /* Examine the instruction before this one to make sure it is
4753 * not a skip type instruction */
4754 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4756 /* This approach does not honor the presence of labels at this instruction... */
4757 //if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4758 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4760 // cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4762 if (!PCI(pc)->pcflow)
4763 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4765 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4771 /*-----------------------------------------------------------------*/
4772 /*-----------------------------------------------------------------*/
4774 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4782 pc = findNextInstruction(pcfl->pc.next);
4784 while(isPCinFlow(pc,PCODE(pcfl))) {
4786 cur_bank = DoBankSelect(pc,cur_bank);
4788 pc = findNextInstruction(pc->next);
4792 if(pcprev && cur_bank) {
4793 // Set bank state to unknown at the end of each flow block
4799 /*-----------------------------------------------------------------*/
4800 /*int compareBankFlow - compare the banking requirements between */
4802 /*-----------------------------------------------------------------*/
4804 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4807 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4810 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4813 if(pcflow->firstBank == -1)
4817 if(pcflowLink->pcflow->firstBank == -1) {
4818 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4819 pcflowLink->pcflow->to :
4820 pcflowLink->pcflow->from);
4821 return compareBankFlow(pcflow, pctl, toORfrom);
4825 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4828 pcflowLink->bank_conflict++;
4829 pcflowLink->pcflow->FromConflicts++;
4830 pcflow->ToConflicts++;
4833 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4836 pcflowLink->bank_conflict++;
4837 pcflowLink->pcflow->ToConflicts++;
4838 pcflow->FromConflicts++;
4842 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4843 pcflowLink->pcflow->pc.seq,
4844 pcflowLink->pcflow->FromConflicts,
4845 pcflowLink->pcflow->ToConflicts);
4851 /*-----------------------------------------------------------------*/
4852 /*-----------------------------------------------------------------*/
4854 void FixBankFlow(pBlock *pb)
4858 pCodeFlowLink *pcfl;
4860 pCode *pcflow_max_To=NULL;
4861 pCode *pcflow_max_From=NULL;
4862 int max_ToConflicts=0;
4863 int max_FromConflicts=0;
4865 /fprintf(stderr,"Fix Bank flow \n");
4866 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4870 First loop through all of the flow objects in this pcode block
4871 and fix the ones that have banking conflicts between the
4875 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4877 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4879 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4881 if(!isPCFL(pcflow)) {
4882 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4886 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4887 PCFL(pcflow)->firstBank >= 0 &&
4888 PCFL(pcflow)->lastBank >= 0 ) {
4890 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4891 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4893 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4894 BanksUsedFlow2(pcflow);
4899 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4901 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4903 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4908 if(!isPCFL(pcflow)) {
4909 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4913 PCFL(pcflow)->FromConflicts = 0;
4914 PCFL(pcflow)->ToConflicts = 0;
4919 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4920 pcfl = setFirstItem(PCFL(pcflow)->from);
4923 pc = PCODE(pcfl->pcflow);
4926 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4927 pc->print(stderr,pc);
4930 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4933 pcfl=setNextItem(PCFL(pcflow)->from);
4936 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4937 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4939 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4940 BanksUsedFlow2(pcflow);
4942 continue; / * Don't need to check the flow from here - it's already been fixed * /
4949 pcfl = setFirstItem(PCFL(pcflow)->to);
4952 pc = PCODE(pcfl->pcflow);
4954 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4955 pc->print(stderr,pc);
4958 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4961 pcfl=setNextItem(PCFL(pcflow)->to);
4964 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4965 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4967 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4968 BanksUsedFlow2(pcflow);
4973 Loop through the flow objects again and find the ones with the
4977 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4979 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4981 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4982 pcflow_max_To = pcflow;
4984 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4985 pcflow_max_From = pcflow;
4989 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4990 PCFL(pcflow_max_To)->pc.seq,
4991 PCFL(pcflow_max_To)->ToConflicts);
4994 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4995 PCFL(pcflow_max_From)->pc.seq,
4996 PCFL(pcflow_max_From)->FromConflicts);
5001 /*-----------------------------------------------------------------*/
5002 /*-----------------------------------------------------------------*/
5003 void DumpFlow(pBlock *pb)
5007 pCodeFlowLink *pcfl;
5010 fprintf(stderr,"Dump flow \n");
5011 pb->pcHead->print(stderr, pb->pcHead);
5013 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5014 pcflow->print(stderr,pcflow);
5016 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5018 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
5020 if(!isPCFL(pcflow)) {
5021 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5024 fprintf(stderr,"dumping: ");
5025 pcflow->print(stderr,pcflow);
5026 FlowStats(PCFL(pcflow));
5028 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5030 pc = PCODE(pcfl->pcflow);
5032 fprintf(stderr, " from seq %d:\n",pc->seq);
5034 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5035 pc->print(stderr,pc);
5040 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5042 pc = PCODE(pcfl->pcflow);
5044 fprintf(stderr, " to seq %d:\n",pc->seq);
5046 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5047 pc->print(stderr,pc);
5056 /*-----------------------------------------------------------------*/
5057 /*-----------------------------------------------------------------*/
5058 int OptimizepBlock(pBlock *pb)
5063 if(!pb || options.nopeep)
5066 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5068 for(pc = pb->pcHead; pc; pc = pc->next)
5069 matches += pCodePeepMatchRule(pc);
5072 pc = findNextInstruction(pb->pcHead);
5080 if(pCodePeepMatchRule(pc)) {
5085 pc = findNextInstruction(pcprev->next);
5087 pc = findNextInstruction(pb->pcHead);
5089 pc = findNextInstruction(pc->next);
5093 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5098 /*-----------------------------------------------------------------*/
5099 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5100 /*-----------------------------------------------------------------*/
5101 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5105 for(pc = pcs; pc; pc = pc->next) {
5107 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5109 (PCI(pc)->pcop->type == PO_LABEL) &&
5110 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5117 /*-----------------------------------------------------------------*/
5118 /*-----------------------------------------------------------------*/
5119 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5126 (PCI(pc)->pcop->type == PO_LABEL)) {
5128 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5130 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5132 free(pcol->pcop.name);
5134 /* If the key is negative, then we (probably) have a label to
5135 * a function and the name is already defined */
5138 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5142 //sprintf(buffer,"_%05d_DS_",pcl->key);
5144 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5146 pcol->pcop.name = Safe_strdup(s);
5147 pcol->key = pcl->key;
5148 //pc->print(stderr,pc);
5155 /*-----------------------------------------------------------------*/
5156 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5157 /* pCode chain if they're not used. */
5158 /*-----------------------------------------------------------------*/
5159 void pBlockRemoveUnusedLabels(pBlock *pb)
5161 pCode *pc; pCodeLabel *pcl;
5166 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5168 pBranch *pbr = PCI(pc)->label;
5169 if(pbr && pbr->next) {
5170 pCode *pcd = pb->pcHead;
5172 //fprintf(stderr, "multiple labels\n");
5173 //pc->print(stderr,pc);
5178 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5179 //fprintf(stderr,"Used by:\n");
5180 //pcd->print(stderr,pcd);
5182 exchangeLabels(PCL(pbr->pc),pcd);
5191 for(pc = pb->pcHead; pc; pc = pc->next) {
5193 if(isPCL(pc)) // Label pcode
5195 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5196 pcl = PCL(PCI(pc)->label->pc);
5199 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5201 /* This pCode is a label, so search the pBlock to see if anyone
5204 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5205 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5206 /* Couldn't find an instruction that refers to this label
5207 * So, unlink the pCode label from it's pCode chain
5208 * and destroy the label */
5209 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5211 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5212 if(pc->type == PC_LABEL) {
5214 pCodeLabelDestruct(pc);
5216 unlinkpCodeFromBranch(pc, PCODE(pcl));
5217 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5228 /*-----------------------------------------------------------------*/
5229 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5230 /* chain and put them into pBranches that are */
5231 /* associated with the appropriate pCode */
5233 /*-----------------------------------------------------------------*/
5234 void pBlockMergeLabels(pBlock *pb)
5237 pCode *pc, *pcnext=NULL;
5242 /* First, Try to remove any unused labels */
5243 //pBlockRemoveUnusedLabels(pb);
5245 /* Now loop through the pBlock and merge the labels with the opcodes */
5248 // for(pc = pb->pcHead; pc; pc = pc->next) {
5251 pCode *pcn = pc->next;
5253 if(pc->type == PC_LABEL) {
5255 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5256 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5257 if((pcnext = findNextInstruction(pc) )) {
5259 // Unlink the pCode label from it's pCode chain
5262 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5263 // And link it into the instruction's pBranch labels. (Note, since
5264 // it's possible to have multiple labels associated with one instruction
5265 // we must provide a means to accomodate the additional labels. Thus
5266 // the labels are placed into the singly-linked list "label" as
5267 // opposed to being a single member of the pCodeInstruction.)
5269 //_ALLOC(pbr,sizeof(pBranch));
5270 pbr = Safe_calloc(1,sizeof(pBranch));
5274 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5277 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5279 } else if(pc->type == PC_CSOURCE) {
5281 /* merge the source line symbolic info into the next instruction */
5282 if((pcnext = findNextInstruction(pc) )) {
5284 // Unlink the pCode label from it's pCode chain
5286 PCI(pcnext)->cline = PCCS(pc);
5287 //fprintf(stderr, "merging CSRC\n");
5288 //genericPrint(stderr,pcnext);
5294 pBlockRemoveUnusedLabels(pb);
5298 /*-----------------------------------------------------------------*/
5299 /*-----------------------------------------------------------------*/
5300 int OptimizepCode(char dbName)
5302 #define MAX_PASSES 4
5311 DFPRINTF((stderr," Optimizing pCode\n"));
5315 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5316 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5317 matches += OptimizepBlock(pb);
5320 while(matches && ++passes < MAX_PASSES);
5325 /*-----------------------------------------------------------------*/
5326 /* popCopyGPR2Bit - copy a pcode operator */
5327 /*-----------------------------------------------------------------*/
5329 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5333 pcop = newpCodeOpBit(pc->name, bitval, 0);
5335 if( !( (pcop->type == PO_LABEL) ||
5336 (pcop->type == PO_LITERAL) ||
5337 (pcop->type == PO_STR) ))
5338 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5344 /*-----------------------------------------------------------------*/
5345 /*-----------------------------------------------------------------*/
5346 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5349 int firstBank = 'U';
5354 for (pc=pb->pcHead; pc; pc=pc->next) {
5356 firstBank = PCFL(pc)->firstBank;
5360 if (firstBank != 'U') {
5361 /* This block has already been done */
5362 if (firstBank != cur_bank) {
5363 /* This block has started with a different bank - must adjust it */
5364 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5367 regs *reg = getRegFromInstruction(pc);
5369 DoBankSelect(pc,cur_bank);
5379 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5382 for (pc=pb->pcHead; pc; pc=pc->next) {
5384 PCFL(pc)->firstBank = cur_bank;
5387 cur_bank = DoBankSelect(pc,cur_bank);
5390 /* Trace through branches and set the bank selection as required. */
5393 for (pc=pb->pcHead; pc; pc=pc->next) {
5395 PCFL(pc)->firstBank = cur_bank;
5399 if (PCI(pc)->op == POC_GOTO) {
5400 int lastRegIdx = LastRegIdx;
5402 /* Trace through branch */
5403 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5406 regs *reg = getRegFromInstruction(pcl);
5408 int bankUnknown = -1;
5409 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5411 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5417 LastRegIdx = lastRegIdx;
5419 /* Keep track out current bank */
5420 regs *reg = getRegFromInstruction(pc);
5422 IsBankChange(pc,reg,&cur_bank);
5429 /*-----------------------------------------------------------------*/
5430 /*-----------------------------------------------------------------*/
5431 void pBlockDestruct(pBlock *pb)
5442 /*-----------------------------------------------------------------*/
5443 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5444 /* name dbName and combine them */
5445 /* into one block */
5446 /*-----------------------------------------------------------------*/
5447 void mergepBlocks(char dbName)
5450 pBlock *pb, *pbmerged = NULL,*pbn;
5452 pb = the_pFile->pbHead;
5454 //fprintf(stderr," merging blocks named %c\n",dbName);
5458 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5459 if( getpBlock_dbName(pb) == dbName) {
5461 //fprintf(stderr," merged block %c\n",dbName);
5466 addpCode2pBlock(pbmerged, pb->pcHead);
5467 /* addpCode2pBlock doesn't handle the tail: */
5468 pbmerged->pcTail = pb->pcTail;
5470 pb->prev->next = pbn;
5472 pbn->prev = pb->prev;
5477 //printpBlock(stderr, pbmerged);
5484 /*-----------------------------------------------------------------*/
5485 /* AnalyzeFlow - Examine the flow of the code and optimize */
5487 /* level 0 == minimal optimization */
5488 /* optimize registers that are used only by two instructions */
5489 /* level 1 == maximal optimization */
5490 /* optimize by looking at pairs of instructions that use the */
5492 /*-----------------------------------------------------------------*/
5494 void AnalyzeFlow(int level)
5496 static int times_called=0;
5504 /* if this is not the first time this function has been called,
5505 then clean up old flow information */
5506 if(times_called++) {
5507 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5510 RegsUnMapLiveRanges();
5516 /* Phase 2 - Flow Analysis - Register Banking
5518 * In this phase, the individual flow blocks are examined
5519 * and register banking is fixed.
5522 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5523 //FixRegisterBanking(pb);
5525 /* Phase 2 - Flow Analysis
5527 * In this phase, the pCode is partition into pCodeFlow
5528 * blocks. The flow blocks mark the points where a continuous
5529 * stream of instructions changes flow (e.g. because of
5530 * a call or goto or whatever).
5533 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5537 /* Phase 2 - Flow Analysis - linking flow blocks
5539 * In this phase, the individual flow blocks are examined
5540 * to determine their order of excution.
5543 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5546 /* Phase 3 - Flow Analysis - Flow Tree
5548 * In this phase, the individual flow blocks are examined
5549 * to determine their order of excution.
5552 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5556 /* Phase x - Flow Analysis - Used Banks
5558 * In this phase, the individual flow blocks are examined
5559 * to determine the Register Banks they use
5562 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5566 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5567 pCodeRegMapLiveRanges(pb);
5569 RemoveUnusedRegisters();
5571 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5572 pCodeRegOptimizeRegUsage(level);
5577 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5582 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5584 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5585 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5586 pcflow = pcflow->next) {
5588 FillFlow(PCFL(pcflow));
5593 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5595 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5596 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5597 pcflow = pcflow->next) {
5599 FlowStats(PCFL(pcflow));
5605 /*-----------------------------------------------------------------*/
5606 /* AnalyzeBanking - Called after the memory addresses have been */
5607 /* assigned to the registers. */
5609 /*-----------------------------------------------------------------*/
5611 void AnalyzeBanking(void)
5615 if(!picIsInitialized()) {
5616 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5620 if (!the_pFile) return;
5622 /* Phase x - Flow Analysis - Used Banks
5624 * In this phase, the individual flow blocks are examined
5625 * to determine the Register Banks they use
5631 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5632 // BanksUsedFlow(pb);
5633 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5634 FixRegisterBanking(pb,-1); // cur_bank is unknown
5638 /*-----------------------------------------------------------------*/
5639 /*-----------------------------------------------------------------*/
5640 DEFSETFUNC (resetrIdx)
5642 regs *r = (regs *)item;
5650 /*-----------------------------------------------------------------*/
5651 /* InitRegReuse - Initialises variables for code analyzer */
5652 /*-----------------------------------------------------------------*/
5654 void InitReuseReg(void)
5656 /* Find end of statically allocated variables for start idx */
5657 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5659 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5660 if (r->type != REG_SFR) {
5661 maxIdx += r->size; /* Increment for all statically allocated variables */
5665 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5668 /*-----------------------------------------------------------------*/
5669 /*-----------------------------------------------------------------*/
5670 static unsigned register_reassign(pBlock *pb, unsigned idx)
5674 /* check recursion */
5675 pc = setFirstItem(pb->function_entries);
5681 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5683 if (pb->tregisters) {
5685 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5686 if (r->type == REG_GPR) {
5688 if (r->rIdx < (int)idx) {
5691 if (peakIdx < idx) peakIdx = idx;
5692 sprintf(s,"r0x%02X", r->rIdx);
5693 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5695 r->name = Safe_strdup(s);
5701 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5703 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5704 char *dest = get_op_from_instruction(PCI(pc));
5706 pCode *pcn = findFunction(dest);
5708 register_reassign(pcn->pb,idx);
5717 /*------------------------------------------------------------------*/
5718 /* ReuseReg were call tree permits */
5720 /* Re-allocate the GPR for optimum reuse for a given pblock */
5721 /* eg if a function m() calls function f1() and f2(), where f1 */
5722 /* allocates a local variable vf1 and f2 allocates a local */
5723 /* variable vf2. Then providing f1 and f2 do not call each other */
5724 /* they may share the same general purpose registers for vf1 and */
5726 /* This is done by first setting the the regs rIdx to start after */
5727 /* all the global variables, then walking through the call tree */
5728 /* renaming the registers to match their new idx and incrementng */
5729 /* it as it goes. If a function has already been called it will */
5730 /* only rename the registers if it has already used up those */
5731 /* registers ie rIdx of the function's registers is lower than the */
5732 /* current rIdx. That way the register will not be reused while */
5733 /* still being used by an eariler function call. */
5735 /* Note for this to work the functions need to be declared static. */
5737 /*------------------------------------------------------------------*/
5741 if (!the_pFile) return;
5743 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5744 /* Non static functions can be called from other modules so their registers must reassign */
5745 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5746 register_reassign(pb,peakIdx);
5750 /*-----------------------------------------------------------------*/
5751 /* buildCallTree - look at the flow and extract all of the calls */
5753 /*-----------------------------------------------------------------*/
5755 void buildCallTree(void )
5764 /* Now build the call tree.
5765 First we examine all of the pCodes for functions.
5766 Keep in mind that the function boundaries coincide
5767 with pBlock boundaries.
5769 The algorithm goes something like this:
5770 We have two nested loops. The outer loop iterates
5771 through all of the pBlocks/functions. The inner
5772 loop iterates through all of the pCodes for
5773 a given pBlock. When we begin iterating through
5774 a pBlock, the variable pc_fstart, pCode of the start
5775 of a function, is cleared. We then search for pCodes
5776 of type PC_FUNCTION. When one is encountered, we
5777 initialize pc_fstart to this and at the same time
5778 associate a new pBranch object that signifies a
5779 branch entry. If a return is found, then this signifies
5780 a function exit point. We'll link the pCodes of these
5781 returns to the matching pc_fstart.
5783 When we're done, a doubly linked list of pBranches
5784 will exist. The head of this list is stored in
5785 `the_pFile', which is the meta structure for all
5786 of the pCode. Look at the printCallTree function
5787 on how the pBranches are linked together.
5790 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5791 pCode *pc_fstart=NULL;
5792 for(pc = pb->pcHead; pc; pc = pc->next) {
5794 pCodeFunction *pcf = PCF(pc);
5797 if(STRCASECMP(pcf->fname, "_main") == 0) {
5798 //fprintf(stderr," found main \n");
5799 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5803 pbr = Safe_calloc(1,sizeof(pBranch));
5804 pbr->pc = pc_fstart = pc;
5807 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5809 // Here's a better way of doing the same:
5810 addSet(&pb->function_entries, pc);
5813 // Found an exit point in a function, e.g. return
5814 // (Note, there may be more than one return per function)
5816 pBranchLink(PCF(pc_fstart), pcf);
5818 addSet(&pb->function_exits, pc);
5820 } else if(isCALL(pc)) {
5821 addSet(&pb->function_calls,pc);
5827 /*-----------------------------------------------------------------*/
5828 /* AnalyzepCode - parse the pCode that has been generated and form */
5829 /* all of the logical connections. */
5831 /* Essentially what's done here is that the pCode flow is */
5833 /*-----------------------------------------------------------------*/
5835 void AnalyzepCode(char dbName)
5846 /* Phase 1 - Register allocation and peep hole optimization
5848 * The first part of the analysis is to determine the registers
5849 * that are used in the pCode. Once that is done, the peep rules
5850 * are applied to the code. We continue to loop until no more
5851 * peep rule optimizations are found (or until we exceed the
5852 * MAX_PASSES threshold).
5854 * When done, the required registers will be determined.
5860 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5862 /* First, merge the labels with the instructions */
5863 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5864 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5866 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5867 pBlockMergeLabels(pb);
5870 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5874 changes = OptimizepCode(dbName);
5876 } while(changes && (i++ < MAX_PASSES));
5881 /*-----------------------------------------------------------------*/
5882 /* ispCodeFunction - returns true if *pc is the pCode of a */
5884 /*-----------------------------------------------------------------*/
5885 bool ispCodeFunction(pCode *pc)
5888 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5894 /*-----------------------------------------------------------------*/
5895 /* findFunction - Search for a function by name (given the name) */
5896 /* in the set of all functions that are in a pBlock */
5897 /* (note - I expect this to change because I'm planning to limit */
5898 /* pBlock's to just one function declaration */
5899 /*-----------------------------------------------------------------*/
5900 pCode *findFunction(char *fname)
5907 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5909 pc = setFirstItem(pb->function_entries);
5912 if((pc->type == PC_FUNCTION) &&
5914 (strcmp(fname, PCF(pc)->fname)==0))
5917 pc = setNextItem(pb->function_entries);
5925 void MarkUsedRegisters(set *regset)
5930 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5931 r2 = pic14_regWithIdx(r1->rIdx);
5939 void pBlockStats(FILE *of, pBlock *pb)
5945 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5947 // for now just print the first element of each set
5948 pc = setFirstItem(pb->function_entries);
5950 fprintf(of,";entry: ");
5953 pc = setFirstItem(pb->function_exits);
5955 fprintf(of,";has an exit\n");
5959 pc = setFirstItem(pb->function_calls);
5961 fprintf(of,";functions called:\n");
5964 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5965 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5967 pc = setNextItem(pb->function_calls);
5971 r = setFirstItem(pb->tregisters);
5973 int n = elementsInSet(pb->tregisters);
5975 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5978 fprintf(of,"; %s\n",r->name);
5979 r = setNextItem(pb->tregisters);
5984 /*-----------------------------------------------------------------*/
5985 /*-----------------------------------------------------------------*/
5987 static void sequencepCode(void)
5993 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5995 pb->seq = GpCodeSequenceNumber+1;
5997 for( pc = pb->pcHead; pc; pc = pc->next)
5998 pc->seq = ++GpCodeSequenceNumber;
6004 /*-----------------------------------------------------------------*/
6005 /*-----------------------------------------------------------------*/
6007 set *register_usage(pBlock *pb)
6010 set *registers=NULL;
6011 set *registersInCallPath = NULL;
6013 / * check recursion * /
6015 pc = setFirstItem(pb->function_entries);
6022 if(pc->type != PC_FUNCTION)
6023 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6025 pc = setFirstItem(pb->function_calls);
6026 for( ; pc; pc = setNextItem(pb->function_calls)) {
6028 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6029 char *dest = get_op_from_instruction(PCI(pc));
6031 pcn = findFunction(dest);
6033 registersInCallPath = register_usage(pcn->pb);
6035 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6040 pBlockStats(stderr,pb); // debug
6043 // Mark the registers in this block as used.
6045 MarkUsedRegisters(pb->tregisters);
6046 if(registersInCallPath) {
6047 / * registers were used in the functions this pBlock has called * /
6048 / * so now, we need to see if these collide with the ones we are * /
6051 regs *r1,*r2, *newreg;
6053 DFPRINTF((stderr,"comparing registers\n"));
6055 r1 = setFirstItem(registersInCallPath);
6057 if (r1->type != REG_STK) {
6058 r2 = setFirstItem(pb->tregisters);
6060 while(r2 && (r2->type != REG_STK)) {
6062 if(r2->rIdx == r1->rIdx) {
6063 newreg = pic14_findFreeReg(REG_GPR);
6067 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6071 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6072 r1->rIdx, newreg->rIdx));
6073 r2->rIdx = newreg->rIdx;
6075 r2->name = Safe_strdup(newreg->name);
6079 newreg->wasUsed = 1;
6081 r2 = setNextItem(pb->tregisters);
6085 r1 = setNextItem(registersInCallPath);
6088 / * Collisions have been resolved. Now free the registers in the call path * /
6089 r1 = setFirstItem(registersInCallPath);
6091 newreg = pic14_regWithIdx(r1->rIdx);
6092 if (newreg) newreg->isFree = 1;
6093 r1 = setNextItem(registersInCallPath);
6097 // MarkUsedRegisters(pb->registers);
6099 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6102 DFPRINTF((stderr,"returning regs\n"));
6104 DFPRINTF((stderr,"not returning regs\n"));
6106 DFPRINTF((stderr,"pBlock after register optim.\n"));
6107 pBlockStats(stderr,pb); // debug
6114 /*-----------------------------------------------------------------*/
6115 /* printCallTree - writes the call tree to a file */
6117 /*-----------------------------------------------------------------*/
6118 void pct2(FILE *of,pBlock *pb,int indent)
6122 // set *registersInCallPath = NULL;
6128 return; //recursion ?
6130 pc = setFirstItem(pb->function_entries);
6137 for(i=0;i<indent;i++) // Indentation
6140 if(pc->type == PC_FUNCTION)
6141 fprintf(of,"%s\n",PCF(pc)->fname);
6146 pc = setFirstItem(pb->function_calls);
6147 for( ; pc; pc = setNextItem(pb->function_calls)) {
6149 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6150 char *dest = get_op_from_instruction(PCI(pc));
6152 pcn = findFunction(dest);
6154 pct2(of,pcn->pb,indent+1);
6156 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6164 /*-----------------------------------------------------------------*/
6165 /* printCallTree - writes the call tree to a file */
6167 /*-----------------------------------------------------------------*/
6169 void printCallTree(FILE *of)
6181 fprintf(of, "\npBlock statistics\n");
6182 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6187 fprintf(of,"Call Tree\n");
6188 pbr = the_pFile->functions;
6192 if(!ispCodeFunction(pc))
6193 fprintf(of,"bug in call tree");
6196 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6198 while(pc->next && !ispCodeFunction(pc->next)) {
6200 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6201 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6209 fprintf(of,"\n**************\n\na better call tree\n");
6210 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6215 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6216 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6222 /*-----------------------------------------------------------------*/
6224 /*-----------------------------------------------------------------*/
6226 void InlineFunction(pBlock *pb)
6234 pc = setFirstItem(pb->function_calls);
6236 for( ; pc; pc = setNextItem(pb->function_calls)) {
6239 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6240 pCode *pcp = pc->prev;
6246 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 */
6248 InlineFunction(pcn->pb);
6251 At this point, *pc points to a CALL mnemonic, and
6252 *pcn points to the function that is being called.
6254 To in-line this call, we need to remove the CALL
6255 and RETURN(s), and link the function pCode in with
6262 /* Check if previous instruction was a bit skip */
6263 if (isPCI_BITSKIP(pcp)) {
6265 /* Invert skip instruction and add a goto */
6266 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6268 if(isPCL(pc_call->next)) { // Label pcode
6269 pcl = PCL(pc_call->next);
6270 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6271 pcl = PCL(PCI(pc_call->next)->label->pc);
6273 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6274 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6276 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6279 /* remove callee pBlock from the pBlock linked list */
6280 removepBlock(pcn->pb);
6288 /* Remove the Function pCode */
6289 pct = findNextInstruction(pcn->next);
6291 /* Link the function with the callee */
6292 if (pcp) pcp->next = pcn->next;
6293 pcn->next->prev = pcp;
6295 /* Convert the function name into a label */
6297 pbr = Safe_calloc(1,sizeof(pBranch));
6298 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6300 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6301 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6303 /* turn all of the return's except the last into goto's */
6304 /* check case for 2 instruction pBlocks */
6305 pce = findNextInstruction(pcn->next);
6307 pCode *pce_next = findNextInstruction(pce->next);
6309 if(pce_next == NULL) {
6310 /* found the last return */
6311 pCode *pc_call_next = findNextInstruction(pc_call->next);
6313 //fprintf(stderr,"found last return\n");
6314 //pce->print(stderr,pce);
6315 pce->prev->next = pc_call->next;
6316 pc_call->next->prev = pce->prev;
6317 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6326 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6332 /*-----------------------------------------------------------------*/
6334 /*-----------------------------------------------------------------*/
6336 void InlinepCode(void)
6345 if(!functionInlining)
6348 /* Loop through all of the function definitions and count the
6349 * number of times each one is called */
6350 //fprintf(stderr,"inlining %d\n",__LINE__);
6352 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6354 pc = setFirstItem(pb->function_calls);
6356 for( ; pc; pc = setNextItem(pb->function_calls)) {
6359 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6360 if(pcn && isPCF(pcn)) {
6361 PCF(pcn)->ncalled++;
6364 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6369 //fprintf(stderr,"inlining %d\n",__LINE__);
6371 /* Now, Loop through the function definitions again, but this
6372 * time inline those functions that have only been called once. */
6374 InlineFunction(the_pFile->pbHead);
6375 //fprintf(stderr,"inlining %d\n",__LINE__);
6377 for(pb = the_pFile->pbHead; pb; pb = pb->next)