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
546 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
547 PCC_REGISTER, // inCond
548 PCC_REGISTER | PCC_Z // outCond
551 pCodeInstruction pciDECFSZW = {
552 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
565 0,0, // dest, bit instruction
567 0, // literal operand
568 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
569 PCC_REGISTER, // inCond
570 PCC_W | PCC_Z // outCond
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
656 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
657 PCC_REGISTER, // inCond
658 PCC_REGISTER | PCC_Z // outCond
661 pCodeInstruction pciINCFSZW = {
662 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
675 0,0, // dest, bit instruction
677 0, // literal operand
678 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
679 PCC_REGISTER, // inCond
680 PCC_W | PCC_Z // outCond
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);
2342 if (!sym) sym = symFindWithName(reg, name);
2343 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2344 // XXX: This ignores nesting levels, but works for globals...
2345 if (!sym) sym = findSym(SymbolTab, NULL, name);
2346 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2348 r = allocNewDirReg(sym->etype,name);
2354 PCOR(pcop)->rIdx = r->rIdx;
2356 pcop->name = Safe_strdup(name);
2357 PCOR(pcop)->r = NULL;
2358 PCOR(pcop)->rIdx = 0;
2363 /*-----------------------------------------------------------------*
2364 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2366 * If rIdx >=0 then a specific register from the set of registers
2367 * will be selected. If rIdx <0, then a new register will be searched
2369 *-----------------------------------------------------------------*/
2371 pCodeOp *newpCodeOpReg(int rIdx)
2375 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2380 PCOR(pcop)->rIdx = rIdx;
2381 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2383 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2386 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2390 pcop->type = PCOR(pcop)->r->pc_type;
2395 pCodeOp *newpCodeOpRegFromStr(char *name)
2399 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2400 PCOR(pcop)->r = allocRegByName(name, 1);
2401 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2402 pcop->type = PCOR(pcop)->r->pc_type;
2403 pcop->name = PCOR(pcop)->r->name;
2408 pCodeOp *newpCodeOpStr(char *name)
2412 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2413 pcop->type = PO_STR;
2414 pcop->name = Safe_strdup(name);
2416 PCOS(pcop)->isPublic = 0;
2422 /*-----------------------------------------------------------------*/
2423 /*-----------------------------------------------------------------*/
2425 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2432 pcop = newpCodeOpBit(name, -1,0);
2436 pcop = newpCodeOpLit(-1);
2440 pcop = newpCodeOpLabel(NULL,-1);
2444 pcop = newpCodeOpReg(-1);
2447 case PO_GPR_POINTER:
2448 case PO_GPR_REGISTER:
2450 pcop = newpCodeOpRegFromStr(name);
2452 pcop = newpCodeOpReg(-1);
2456 pcop = newpCodeOpStr(name);
2460 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2463 pcop->name = Safe_strdup(name);
2471 /*-----------------------------------------------------------------*/
2472 /*-----------------------------------------------------------------*/
2473 void pCodeConstString(char *name, char *value)
2478 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2483 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2487 sprintf(buffer,"; %s = %s",name,value);
2488 for (i=strlen(buffer); i--; ) {
2489 unsigned char c = buffer[i];
2490 if (c=='\r' || c=='\n') {
2491 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2493 if (c=='\r') buffer[i+1] = 'r';
2494 else if (c=='\n') buffer[i+1] = 'n';
2498 addpCode2pBlock(pb,newpCodeCharP(buffer));
2499 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2502 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2508 /*-----------------------------------------------------------------*/
2509 /*-----------------------------------------------------------------*/
2510 void pCodeReadCodeTable(void)
2514 fprintf(stderr, " %s\n",__FUNCTION__);
2516 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2520 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2521 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2522 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2523 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2525 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2526 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2527 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2528 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2533 /*-----------------------------------------------------------------*/
2534 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2535 /*-----------------------------------------------------------------*/
2536 void addpCode2pBlock(pBlock *pb, pCode *pc)
2543 /* If this is the first pcode to be added to a block that
2544 * was initialized with a NULL pcode, then go ahead and
2545 * make this pcode the head and tail */
2546 pb->pcHead = pb->pcTail = pc;
2549 pb->pcTail->next = pc;
2551 pc->prev = pb->pcTail;
2558 /*-----------------------------------------------------------------*/
2559 /* addpBlock - place a pBlock into the pFile */
2560 /*-----------------------------------------------------------------*/
2561 void addpBlock(pBlock *pb)
2563 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2566 /* First time called, we'll pass through here. */
2567 //_ALLOC(the_pFile,sizeof(pFile));
2568 the_pFile = Safe_calloc(1,sizeof(pFile));
2569 the_pFile->pbHead = the_pFile->pbTail = pb;
2570 the_pFile->functions = NULL;
2574 the_pFile->pbTail->next = pb;
2575 pb->prev = the_pFile->pbTail;
2577 the_pFile->pbTail = pb;
2580 /*-----------------------------------------------------------------*/
2581 /* removepBlock - remove a pBlock from the pFile */
2582 /*-----------------------------------------------------------------*/
2583 void removepBlock(pBlock *pb)
2591 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2593 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2596 if(pbs == the_pFile->pbHead)
2597 the_pFile->pbHead = pbs->next;
2599 if (pbs == the_pFile->pbTail)
2600 the_pFile->pbTail = pbs->prev;
2603 pbs->next->prev = pbs->prev;
2606 pbs->prev->next = pbs->next;
2613 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2617 /*-----------------------------------------------------------------*/
2618 /* printpCode - write the contents of a pCode to a file */
2619 /*-----------------------------------------------------------------*/
2620 void printpCode(FILE *of, pCode *pc)
2631 fprintf(of,"warning - unable to print pCode\n");
2634 /*-----------------------------------------------------------------*/
2635 /* printpBlock - write the contents of a pBlock to a file */
2636 /*-----------------------------------------------------------------*/
2637 void printpBlock(FILE *of, pBlock *pb)
2647 for(pc = pb->pcHead; pc; pc = pc->next) {
2652 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2662 /*-----------------------------------------------------------------*/
2664 /* pCode processing */
2668 /*-----------------------------------------------------------------*/
2670 void unlinkpCode(pCode *pc)
2676 fprintf(stderr,"Unlinking: ");
2677 printpCode(stderr, pc);
2680 pc->prev->next = pc->next;
2682 pc->next->prev = pc->prev;
2685 /* RN: I believe this should be right here, but this did not
2686 * cure the bug I was hunting... */
2687 /* must keep labels -- attach to following instruction */
2688 if (isPCI(pc) && PCI(pc)->label && pc->next)
2690 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2693 pBranchAppend (pcnext->label, PCI(pc)->label);
2697 pc->prev = pc->next = NULL;
2701 /*-----------------------------------------------------------------*/
2702 /*-----------------------------------------------------------------*/
2704 static void genericDestruct(pCode *pc)
2710 /* For instructions, tell the register (if there's one used)
2711 * that it's no longer needed */
2712 regs *reg = getRegFromInstruction(pc);
2714 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2717 /* Instead of deleting the memory used by this pCode, mark
2718 * the object as bad so that if there's a pointer to this pCode
2719 * dangling around somewhere then (hopefully) when the type is
2720 * checked we'll catch it.
2725 addpCode2pBlock(pb_dead_pcodes, pc);
2732 /*-----------------------------------------------------------------*/
2733 /* Copies the pCodeInstruction flow pointer from source pCode */
2734 /*-----------------------------------------------------------------*/
2735 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2737 pCodeFlow *pcflow = 0;
2738 for (p=pcs; p; p=p->prev) {
2740 pcflow = PCI(p)->pcflow;
2744 pcflow = (pCodeFlow*)p;
2748 PCI(pcd)->pcflow = pcflow;
2751 /*-----------------------------------------------------------------*/
2752 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2753 /* into the pCode chain containing pc1 */
2754 /*-----------------------------------------------------------------*/
2755 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2761 pc2->next = pc1->next;
2763 pc1->next->prev = pc2;
2769 /* If this is an instrution type propogate the flow */
2771 CopyFlow(PCI(pc2),pc1);
2774 /*------------------------------------------------------------------*/
2775 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2776 /* into the pCode chain containing pc1 */
2777 /*------------------------------------------------------------------*/
2778 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2784 pc2->prev = pc1->prev;
2786 pc1->prev->next = pc2;
2792 /* If this is an instrution type propogate the flow */
2794 CopyFlow(PCI(pc2),pc1);
2797 /*-----------------------------------------------------------------*/
2798 /* pCodeOpCopy - copy a pcode operator */
2799 /*-----------------------------------------------------------------*/
2800 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2802 pCodeOp *pcopnew=NULL;
2807 switch(pcop->type) {
2810 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2811 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2819 case PO_GPR_REGISTER:
2821 case PO_GPR_POINTER:
2822 case PO_SFR_REGISTER:
2826 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2827 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2828 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2829 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2833 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2834 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2835 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2839 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2840 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2846 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2847 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2848 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2852 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2853 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2854 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2858 /* Here we expand the wild card into the appropriate type: */
2859 /* By recursively calling pCodeOpCopy */
2860 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2861 if(PCOW(pcop)->matched)
2862 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2865 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2866 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2867 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2874 assert ( !"unhandled pCodeOp type copied" );
2879 pcopnew->name = Safe_strdup(pcop->name);
2881 pcopnew->name = NULL;
2886 /*-----------------------------------------------------------------*/
2887 /* popCopyReg - copy a pcode operator */
2888 /*-----------------------------------------------------------------*/
2889 pCodeOp *popCopyReg(pCodeOpReg *pc)
2893 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2894 pcor->pcop.type = pc->pcop.type;
2896 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2897 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2899 pcor->pcop.name = NULL;
2901 if (pcor->pcop.type == PO_IMMEDIATE){
2902 PCOL(pcor)->lit = PCOL(pc)->lit;
2905 pcor->rIdx = pc->rIdx;
2909 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2914 /*-----------------------------------------------------------------*/
2915 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2916 /*-----------------------------------------------------------------*/
2917 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2919 pCodeInstruction *new_pci;
2922 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2924 new_pci = PCI(newpCode(pci->op,pci->pcop));
2926 new_pci->pc.pb = pci->pc.pb;
2927 new_pci->from = pci->from;
2928 new_pci->to = pci->to;
2929 new_pci->label = pci->label;
2930 new_pci->pcflow = pci->pcflow;
2932 return PCODE(new_pci);
2935 /*-----------------------------------------------------------------*/
2936 /*-----------------------------------------------------------------*/
2937 void pCodeDeleteChain(pCode *f,pCode *t)
2942 DFPRINTF((stderr,"delete pCode:\n"));
2944 //f->print(stderr,f);
2945 //f->delete(f); this dumps core...
2950 /*-----------------------------------------------------------------*/
2951 /*-----------------------------------------------------------------*/
2952 void pBlockRegs(FILE *of, pBlock *pb)
2957 r = setFirstItem(pb->tregisters);
2959 r = setNextItem(pb->tregisters);
2964 /*-----------------------------------------------------------------*/
2965 /*-----------------------------------------------------------------*/
2966 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2971 int use_buffer = 1; // copy the string to the passed buffer pointer
2976 use_buffer = 0; // Don't bother copying the string to the buffer.
2980 switch(pcop->type) {
2984 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2987 //return PCOR(pcop)->r->name;
2991 if (PCOR(pcop)->r->type == REG_STK)
2992 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2994 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2997 SAFE_snprintf(&buffer,&size,"%s",r->name);
3006 if(PCOI(pcop)->_const) {
3008 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3009 switch(PCOI(pcop)->offset) {
3011 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3014 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3017 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3018 assert ( !"offset too large" );
3019 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3022 8 * PCOI(pcop)->offset );
3025 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3027 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3028 SAFE_snprintf(&s,&size,"(%s + %d)",
3032 switch(PCOI(pcop)->offset) {
3034 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3037 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3040 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3041 assert ( !"offset too large" );
3042 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3052 //size = sizeof(buffer);
3053 if( PCOR(pcop)->instance) {
3054 SAFE_snprintf(&s,&size,"(%s + %d)",
3056 PCOR(pcop)->instance );
3057 //fprintf(stderr,"PO_DIR %s\n",buffer);
3059 SAFE_snprintf(&s,&size,"%s",pcop->name);
3065 if(PCOLAB(pcop)->offset == 1)
3066 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3068 SAFE_snprintf(&s,&size,"%s",pcop->name);
3075 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3078 return PCOR(pcop)->r->name;
3081 /* fall through to the default case */
3085 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3093 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3094 __FILE__, __LINE__, __FUNCTION__,
3097 return "NO operand";
3101 /*-----------------------------------------------------------------*/
3102 /*-----------------------------------------------------------------*/
3103 static char *get_op_from_instruction( pCodeInstruction *pcc)
3107 return get_op(pcc->pcop,NULL,0);
3109 return ("ERROR Null: get_op_from_instruction");
3113 /*-----------------------------------------------------------------*/
3114 /*-----------------------------------------------------------------*/
3115 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3117 fprintf(of,"pcodeopprint- not implemented\n");
3120 /*-----------------------------------------------------------------*/
3121 /* pCode2str - convert a pCode instruction to string */
3122 /*-----------------------------------------------------------------*/
3123 char *pCode2str(char *str, size_t size, pCode *pc)
3131 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3133 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3135 if(PCI(pc)->isBitInst) {
3136 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3137 char *name = PCI(pc)->pcop->name;
3139 name = PCOR(PCI(pc)->pcop)->r->name;
3140 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3141 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3143 SAFE_snprintf(&s,&size,"%s,%d", name,
3144 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3145 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3146 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3148 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3149 //PCI(pc)->pcop->t.bit );
3151 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3152 if( PCI(pc)->num_ops == 2)
3153 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3155 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3157 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3158 if( PCI(pc)->num_ops == 2)
3159 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3166 /* assuming that comment ends with a \n */
3167 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3171 /* assuming that inline code ends with a \n */
3172 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3176 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3179 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3182 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3185 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3188 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3189 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);
3192 if(PCAD(pc)->directive) {
3193 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3194 } else if(PCAD(pc)->arg) {
3195 /* special case to handle inline labels without a tab */
3196 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3201 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3207 /*-----------------------------------------------------------------*/
3208 /* genericPrint - the contents of a pCode to a file */
3209 /*-----------------------------------------------------------------*/
3210 static void genericPrint(FILE *of, pCode *pc)
3217 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3221 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3225 // If the opcode has a label, print that first
3228 pCodeInstruction *pci = PCI(pc);
3229 pBranch *pbl = pci->label;
3230 while(pbl && pbl->pc) {
3231 if(pbl->pc->type == PC_LABEL)
3232 pCodePrintLabel(of, pbl->pc);
3237 genericPrint(of,PCODE(pci->cline));
3240 pCode2str(str, 256, pc);
3242 fprintf(of,"%s",str);
3246 pCodeOpReg *pcor = PCOR(pci->pcop);
3247 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3249 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3250 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3251 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3256 pBranch *dpb = pc->to; // debug
3258 switch ( dpb->pc->type) {
3260 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3263 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3266 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3269 fprintf(of, "\t;flow");
3283 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3284 if(PCW(pc)->pci.label)
3285 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3287 if(PCW(pc)->operand) {
3288 fprintf(of,";\toperand ");
3289 pCodeOpPrint(of,PCW(pc)->operand );
3295 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3296 if(PCFL(pc)->ancestor)
3297 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3299 fprintf(of,"; from: ");
3301 pCodeFlowLink *link;
3302 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3304 fprintf(of,"%03x ",link->pcflow->pc.seq);
3307 fprintf(of,"; to: ");
3309 pCodeFlowLink *link;
3310 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3312 fprintf(of,"%03x ",link->pcflow->pc.seq);
3320 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3321 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3326 pBranch *pbl = PCAD(pc)->pci.label;
3327 while(pbl && pbl->pc) {
3328 if(pbl->pc->type == PC_LABEL)
3329 pCodePrintLabel(of, pbl->pc);
3333 if(PCAD(pc)->directive) {
3334 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3337 /* special case to handle inline labels without tab */
3338 fprintf(of, "%s\n", PCAD(pc)->arg);
3344 fprintf(of,"unknown pCode type %d\n",pc->type);
3348 /*-----------------------------------------------------------------*/
3349 /* pCodePrintFunction - prints function begin/end */
3350 /*-----------------------------------------------------------------*/
3352 static void pCodePrintFunction(FILE *of, pCode *pc)
3358 if( ((pCodeFunction *)pc)->modname)
3359 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3361 if(PCF(pc)->fname) {
3362 pBranch *exits = PCF(pc)->to;
3364 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3367 exits = exits->next;
3370 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3373 if((PCF(pc)->from &&
3374 PCF(pc)->from->pc->type == PC_FUNCTION &&
3375 PCF(PCF(pc)->from->pc)->fname) )
3376 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3378 fprintf(of,"; exit point [can't find entry point]\n");
3381 /*-----------------------------------------------------------------*/
3382 /* pCodePrintLabel - prints label */
3383 /*-----------------------------------------------------------------*/
3385 static void pCodePrintLabel(FILE *of, pCode *pc)
3392 fprintf(of,"%s\n",PCL(pc)->label);
3393 else if (PCL(pc)->key >=0)
3394 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3396 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3400 /*-----------------------------------------------------------------*/
3401 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3402 /* remove it if it is found. */
3403 /*-----------------------------------------------------------------*/
3404 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3410 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3411 b = PCI(pcl)->label;
3413 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3417 //fprintf (stderr, "%s \n",__FUNCTION__);
3418 //pcl->print(stderr,pcl);
3419 //pc->print(stderr,pc);
3422 //fprintf (stderr, "found label\n");
3426 bprev->next = b->next; /* Not first pCode in chain */
3430 PCI(pcl)->label = b->next; /* First pCode in chain */
3433 return; /* A label can't occur more than once */
3440 /*-----------------------------------------------------------------*/
3441 /*-----------------------------------------------------------------*/
3442 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3461 /*-----------------------------------------------------------------*/
3462 /* pBranchLink - given two pcodes, this function will link them */
3463 /* together through their pBranches */
3464 /*-----------------------------------------------------------------*/
3465 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3469 // Declare a new branch object for the 'from' pCode.
3471 //_ALLOC(b,sizeof(pBranch));
3472 b = Safe_calloc(1,sizeof(pBranch));
3473 b->pc = PCODE(t); // The link to the 'to' pCode.
3476 f->to = pBranchAppend(f->to,b);
3478 // Now do the same for the 'to' pCode.
3480 //_ALLOC(b,sizeof(pBranch));
3481 b = Safe_calloc(1,sizeof(pBranch));
3485 t->from = pBranchAppend(t->from,b);
3490 /*-----------------------------------------------------------------*/
3491 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3493 /*-----------------------------------------------------------------*/
3494 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3507 /*-----------------------------------------------------------------*/
3508 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3509 /*-----------------------------------------------------------------*/
3510 static void pCodeUnlink(pCode *pc)
3515 if(!pc->prev || !pc->next) {
3516 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3520 /* first remove the pCode from the chain */
3521 pc->prev->next = pc->next;
3522 pc->next->prev = pc->prev;
3524 /* Now for the hard part... */
3526 /* Remove the branches */
3530 pc1 = pb1->pc; /* Get the pCode that branches to the
3531 * one we're unlinking */
3533 /* search for the link back to this pCode (the one we're
3535 if(pb2 = pBranchFind(pc1->to,pc)) {
3536 pb2->pc = pc->to->pc; // make the replacement
3538 /* if the pCode we're unlinking contains multiple 'to'
3539 * branches (e.g. this a skip instruction) then we need
3540 * to copy these extra branches to the chain. */
3542 pBranchAppend(pb2, pc->to->next);
3551 /*-----------------------------------------------------------------*/
3552 /*-----------------------------------------------------------------*/
3554 static void genericAnalyze(pCode *pc)
3564 // Go through the pCodes that are in pCode chain and link
3565 // them together through the pBranches. Note, the pCodes
3566 // are linked together as a contiguous stream like the
3567 // assembly source code lines. The linking here mimics this
3568 // except that comments are not linked in.
3570 pCode *npc = pc->next;
3572 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3573 pBranchLink(pc,npc);
3578 /* reached the end of the pcode chain without finding
3579 * an instruction we could link to. */
3583 fprintf(stderr,"analyze PC_FLOW\n");
3587 fprintf(stderr,";A bad pCode is being used\n");
3593 /*-----------------------------------------------------------------*/
3594 /*-----------------------------------------------------------------*/
3595 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3599 if(pc->type == PC_LABEL) {
3600 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3603 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3604 pbr = PCI(pc)->label;
3606 if(pbr->pc->type == PC_LABEL) {
3607 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3617 /*-----------------------------------------------------------------*/
3618 /*-----------------------------------------------------------------*/
3619 int checkLabel(pCode *pc)
3623 if(pc && isPCI(pc)) {
3624 pbr = PCI(pc)->label;
3626 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3636 /*-----------------------------------------------------------------*/
3637 /* findLabelinpBlock - Search the pCode for a particular label */
3638 /*-----------------------------------------------------------------*/
3639 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3646 for(pc = pb->pcHead; pc; pc = pc->next)
3647 if(compareLabel(pc,pcop_label))
3653 /*-----------------------------------------------------------------*/
3654 /* findLabel - Search the pCode for a particular label */
3655 /*-----------------------------------------------------------------*/
3656 pCode * findLabel(pCodeOpLabel *pcop_label)
3664 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3665 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3669 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3673 /*-----------------------------------------------------------------*/
3674 /* findNextpCode - given a pCode, find the next of type 'pct' */
3675 /* in the linked list */
3676 /*-----------------------------------------------------------------*/
3677 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3690 /*-----------------------------------------------------------------*/
3691 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3692 /* in the linked list */
3693 /*-----------------------------------------------------------------*/
3694 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3698 if(pc->type == pct) {
3700 static unsigned int stop;
3702 stop++; // Place break point here
3713 /*-----------------------------------------------------------------*/
3714 /* findNextInstruction - given a pCode, find the next instruction */
3715 /* in the linked list */
3716 /*-----------------------------------------------------------------*/
3717 pCode * findNextInstruction(pCode *pci)
3722 if((pc->type == PC_OPCODE)
3723 || (pc->type == PC_WILD)
3724 || (pc->type == PC_ASMDIR))
3728 fprintf(stderr,"findNextInstruction: ");
3729 printpCode(stderr, pc);
3734 //fprintf(stderr,"Couldn't find instruction\n");
3738 /*-----------------------------------------------------------------*/
3739 /* findNextInstruction - given a pCode, find the next instruction */
3740 /* in the linked list */
3741 /*-----------------------------------------------------------------*/
3742 pCode * findPrevInstruction(pCode *pci)
3748 if((pc->type == PC_OPCODE)
3749 || (pc->type == PC_WILD)
3750 || (pc->type == PC_ASMDIR))
3755 fprintf(stderr,"pic16_findPrevInstruction: ");
3756 printpCode(stderr, pc);
3761 //fprintf(stderr,"Couldn't find instruction\n");
3765 /*-----------------------------------------------------------------*/
3766 /* findFunctionEnd - given a pCode find the end of the function */
3767 /* that contains it */
3768 /*-----------------------------------------------------------------*/
3769 pCode * findFunctionEnd(pCode *pc)
3772 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3778 fprintf(stderr,"Couldn't find function end\n");
3783 /*-----------------------------------------------------------------*/
3784 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3785 /* instruction with which it is associated. */
3786 /*-----------------------------------------------------------------*/
3787 static void AnalyzeLabel(pCode *pc)
3796 static void AnalyzeGOTO(pCode *pc)
3799 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3803 static void AnalyzeSKIP(pCode *pc)
3806 pBranchLink(pc,findNextInstruction(pc->next));
3807 pBranchLink(pc,findNextInstruction(pc->next->next));
3811 static void AnalyzeRETURN(pCode *pc)
3814 // branch_link(pc,findFunctionEnd(pc->next));
3820 /*-----------------------------------------------------------------*/
3821 /*-----------------------------------------------------------------*/
3822 regs * getRegFromInstruction(pCode *pc)
3828 PCI(pc)->num_ops == 0 )
3831 switch(PCI(pc)->pcop->type) {
3838 case PO_SFR_REGISTER:
3841 return PCOR(PCI(pc)->pcop)->r;
3843 case PO_GPR_REGISTER:
3846 r = PCOR(PCI(pc)->pcop)->r;
3849 return dirregWithName(PCI(pc)->pcop->name);
3855 r = PCOI(PCI(pc)->pcop)->r;
3858 return dirregWithName(PCI(pc)->pcop->name);
3868 /*-----------------------------------------------------------------*/
3869 /*-----------------------------------------------------------------*/
3871 void AnalyzepBlock(pBlock *pb)
3878 /* Find all of the registers used in this pBlock
3879 * by looking at each instruction and examining it's
3882 for(pc = pb->pcHead; pc; pc = pc->next) {
3884 /* Is this an instruction with operands? */
3885 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3887 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3888 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3890 /* Loop through all of the registers declared so far in
3891 this block and see if we find this one there */
3893 regs *r = setFirstItem(pb->tregisters);
3896 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3897 PCOR(PCI(pc)->pcop)->r = r;
3900 r = setNextItem(pb->tregisters);
3904 /* register wasn't found */
3905 //r = Safe_calloc(1, sizeof(regs));
3906 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3907 //addSet(&pb->tregisters, r);
3908 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3909 //PCOR(PCI(pc)->pcop)->r = r;
3910 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3912 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3915 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3916 if(PCOR(PCI(pc)->pcop)->r) {
3917 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3918 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3920 if(PCI(pc)->pcop->name)
3921 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3923 fprintf(stderr,"ERROR: NULL register\n");
3932 /*-----------------------------------------------------------------*/
3934 /*-----------------------------------------------------------------*/
3935 void InsertpFlow(pCode *pc, pCode **pflow)
3938 PCFL(*pflow)->end = pc;
3940 if(!pc || !pc->next)
3943 *pflow = newpCodeFlow();
3944 pCodeInsertAfter(pc, *pflow);
3947 /*-----------------------------------------------------------------*/
3948 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3949 /* the flow blocks. */
3951 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3952 * point the instruction flow changes.
3954 /*-----------------------------------------------------------------*/
3955 void BuildFlow(pBlock *pb)
3958 pCode *last_pci=NULL;
3965 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3966 /* Insert a pCodeFlow object at the beginning of a pBlock */
3968 InsertpFlow(pb->pcHead, &pflow);
3970 //pflow = newpCodeFlow(); /* Create a new Flow object */
3971 //pflow->next = pb->pcHead; /* Make the current head the next object */
3972 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3973 //pb->pcHead = pflow; /* Make the Flow object the head */
3976 for( pc = findNextInstruction(pb->pcHead);
3978 pc=findNextInstruction(pc)) {
3981 PCI(pc)->pcflow = PCFL(pflow);
3983 //fprintf(stderr," build: ");
3984 //pc->print(stderr, pc);
3985 //pflow->print(stderr,pflow);
3987 if (checkLabel(pc)) {
3989 /* This instruction marks the beginning of a
3990 * new flow segment */
3995 /* If the previous pCode is not a flow object, then
3996 * insert a new flow object. (This check prevents
3997 * two consecutive flow objects from being insert in
3998 * the case where a skip instruction preceeds an
3999 * instruction containing a label.) */
4001 last_pci = findPrevInstruction (pc->prev);
4003 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4004 InsertpFlow(last_pci, &pflow);
4006 PCI(pc)->pcflow = PCFL(pflow);
4010 if(isPCI_SKIP(pc)) {
4012 /* The two instructions immediately following this one
4013 * mark the beginning of a new flow segment */
4015 while(pc && isPCI_SKIP(pc)) {
4017 PCI(pc)->pcflow = PCFL(pflow);
4021 InsertpFlow(pc, &pflow);
4022 pc=findNextInstruction(pc->next);
4030 PCI(pc)->pcflow = PCFL(pflow);
4032 InsertpFlow(pc, &pflow);
4034 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4036 InsertpFlow(pc, &pflow);
4045 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4047 PCFL(pflow)->end = pb->pcTail;
4050 /*-------------------------------------------------------------------*/
4051 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4052 /* the flow blocks. */
4054 * unBuildFlow removes pCodeFlow objects from a pCode chain
4056 /*-----------------------------------------------------------------*/
4057 void unBuildFlow(pBlock *pb)
4072 if(PCI(pc)->pcflow) {
4073 //free(PCI(pc)->pcflow);
4074 PCI(pc)->pcflow = NULL;
4077 } else if(isPCFL(pc) )
4086 /*-----------------------------------------------------------------*/
4087 /*-----------------------------------------------------------------*/
4088 void dumpCond(int cond)
4091 static char *pcc_str[] = {
4105 int ncond = sizeof(pcc_str) / sizeof(char *);
4108 fprintf(stderr, "0x%04X\n",cond);
4110 for(i=0,j=1; i<ncond; i++, j<<=1)
4112 fprintf(stderr, " %s\n",pcc_str[i]);
4116 /*-----------------------------------------------------------------*/
4117 /*-----------------------------------------------------------------*/
4118 void FlowStats(pCodeFlow *pcflow)
4126 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4128 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4131 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4136 fprintf(stderr, " FlowStats inCond: ");
4137 dumpCond(pcflow->inCond);
4138 fprintf(stderr, " FlowStats outCond: ");
4139 dumpCond(pcflow->outCond);
4143 /*-----------------------------------------------------------------*
4144 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4145 * if it affects the banking bits.
4147 * return: -1 == Banking bits are unaffected by this pCode.
4149 * return: > 0 == Banking bits are affected.
4151 * If the banking bits are affected, then the returned value describes
4152 * which bits are affected and how they're affected. The lower half
4153 * of the integer maps to the bits that are affected, the upper half
4154 * to whether they're set or cleared.
4156 *-----------------------------------------------------------------*/
4158 #define SET_BANK_BIT (1 << 16)
4159 #define CLR_BANK_BIT 0
4161 static int isBankInstruction(pCode *pc)
4169 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4171 // Check to see if the register banks are changing
4172 if(PCI(pc)->isModReg) {
4174 pCodeOp *pcop = PCI(pc)->pcop;
4175 switch(PCI(pc)->op) {
4178 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4179 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4180 return SET_BANK_BIT | PIC_RP0_BIT;
4183 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4184 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4185 return CLR_BANK_BIT | PIC_RP0_BIT;
4190 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4191 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4192 return CLR_BANK_BIT | PIC_RP1_BIT;
4194 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4195 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4196 return CLR_BANK_BIT | PIC_RP1_BIT;
4200 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4201 //genericPrint(stderr, pc);
4212 /*-----------------------------------------------------------------*/
4213 /*-----------------------------------------------------------------*/
4215 static void FillFlow(pCodeFlow *pcflow)
4223 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4225 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4228 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4235 isBankInstruction(pc);
4237 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4240 fprintf(stderr, " FillFlow - Bad end of flow\n");
4242 fprintf(stderr, " FillFlow - Ending flow with\n ");
4243 pc->print(stderr,pc);
4246 fprintf(stderr, " FillFlow inCond: ");
4247 dumpCond(pcflow->inCond);
4248 fprintf(stderr, " FillFlow outCond: ");
4249 dumpCond(pcflow->outCond);
4254 /*-----------------------------------------------------------------*/
4255 /*-----------------------------------------------------------------*/
4256 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4258 pCodeFlowLink *fromLink, *toLink;
4260 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4261 if (from) from->pc.print(stderr, &from->pc);
4262 else fprintf(stderr, "(null)");
4263 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4264 from && from->pcflow ? from->pcflow->pc.seq : 0,
4265 to && to->pcflow ? to->pcflow->pc.seq : 0);
4266 if (to) to->pc.print(stderr, &to->pc);
4267 else fprintf(stderr, "(null)");
4270 if(!from || !to || !to->pcflow || !from->pcflow)
4273 fromLink = newpCodeFlowLink(from->pcflow);
4274 toLink = newpCodeFlowLink(to->pcflow);
4276 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4277 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4281 /*-----------------------------------------------------------------*
4282 * void LinkFlow(pBlock *pb)
4284 * In BuildFlow, the PIC code has been partitioned into contiguous
4285 * non-branching segments. In LinkFlow, we determine the execution
4286 * order of these segments. For example, if one of the segments ends
4287 * with a skip, then we know that there are two possible flow segments
4288 * to which control may be passed.
4289 *-----------------------------------------------------------------*/
4290 void LinkFlow(pBlock *pb)
4296 //fprintf(stderr,"linkflow \n");
4298 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4300 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4303 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4305 //fprintf(stderr," link: ");
4306 //pcflow->print(stderr,pcflow);
4308 //FillFlow(PCFL(pcflow));
4310 /* find last instruction in flow */
4311 pc = findPrevInstruction (PCFL(pcflow)->end);
4313 fprintf(stderr, "%s: flow without end (%u)?\n",
4314 __FUNCTION__, pcflow->seq );
4318 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4319 //pc->print(stderr, pc);
4320 if(isPCI_SKIP(pc)) {
4321 //fprintf(stderr, "ends with skip\n");
4322 //pc->print(stderr,pc);
4323 pct=findNextInstruction(pc->next);
4324 LinkFlow_pCode(PCI(pc),PCI(pct));
4325 pct=findNextInstruction(pct->next);
4326 LinkFlow_pCode(PCI(pc),PCI(pct));
4330 if(isPCI_BRANCH(pc)) {
4331 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4333 //fprintf(stderr, "ends with branch\n ");
4334 //pc->print(stderr,pc);
4336 if(!(pcol && isPCOLAB(pcol))) {
4337 if((PCI(pc)->op != POC_RETLW)
4338 && (PCI(pc)->op != POC_RETURN)
4339 && (PCI(pc)->op != POC_CALL)
4340 && (PCI(pc)->op != POC_RETFIE) )
4342 pc->print(stderr,pc);
4343 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4347 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4348 LinkFlow_pCode(PCI(pc),PCI(pct));
4350 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4351 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4352 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4354 /* link CALLs to next instruction */
4355 if (PCI(pc)->op != POC_CALL) continue;
4359 //fprintf(stderr, "ends with non-branching instruction:\n");
4360 //pc->print(stderr,pc);
4362 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4368 //fprintf(stderr, "ends with unknown\n");
4369 //pc->print(stderr,pc);
4373 fprintf(stderr, "ends with nothing: ERROR\n");
4377 /*-----------------------------------------------------------------*/
4378 /*-----------------------------------------------------------------*/
4380 /*-----------------------------------------------------------------*/
4381 /*-----------------------------------------------------------------*/
4382 int isPCinFlow(pCode *pc, pCode *pcflow)
4388 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4391 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4397 /*-----------------------------------------------------------------*/
4398 /*-----------------------------------------------------------------*/
4400 static void BanksUsedFlow2(pCode *pcflow)
4409 if(!isPCFL(pcflow)) {
4410 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4414 pc = findNextInstruction(pcflow->next);
4416 PCFL(pcflow)->lastBank = -1;
4418 while(isPCinFlow(pc,pcflow)) {
4420 int bank_selected = isBankInstruction(pc);
4422 //if(PCI(pc)->pcflow)
4423 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4425 if(bank_selected > 0) {
4426 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4428 // This instruction is modifying banking bits before accessing registers
4430 PCFL(pcflow)->firstBank = -1;
4432 if(PCFL(pcflow)->lastBank == -1)
4433 PCFL(pcflow)->lastBank = 0;
4435 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4436 if(bank_selected & SET_BANK_BIT)
4437 PCFL(pcflow)->lastBank |= bank;
4441 reg = getRegFromInstruction(pc);
4443 if(reg && !isREGinBank(reg, bank)) {
4444 int allbanks = REGallBanks(reg);
4446 PCFL(pcflow)->firstBank = allbanks;
4448 PCFL(pcflow)->lastBank = allbanks;
4455 pc = findNextInstruction(pc->next);
4458 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4459 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4462 /*-----------------------------------------------------------------*/
4463 /*-----------------------------------------------------------------*/
4465 static void BanksUsedFlow(pBlock *pb)
4470 //pb->pcHead->print(stderr, pb->pcHead);
4472 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4473 //pcflow->print(stderr,pcflow);
4475 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4477 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4479 BanksUsedFlow2(pcflow);
4485 void pCodeReplace (pCode *old, pCode *new)
4487 pCodeInsertAfter (old, new);
4489 /* special handling for pCodeInstructions */
4490 if (isPCI(new) && isPCI(old))
4492 assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4493 PCI(new)->from = PCI(old)->from;
4494 PCI(new)->to = PCI(old)->to;
4495 PCI(new)->label = PCI(old)->label;
4496 PCI(new)->pcflow = PCI(old)->pcflow;
4497 PCI(new)->cline = PCI(old)->cline;
4500 old->destruct (old);
4503 /*-----------------------------------------------------------------*/
4504 /* Inserts a new pCodeInstruction before an existing one */
4505 /*-----------------------------------------------------------------*/
4506 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4510 pcprev = findPrevInstruction(pci->pc.prev);
4512 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4514 /* Move the label, if there is one */
4517 new_pci->label = pci->label;
4521 /* Move the C code comment, if there is one */
4524 new_pci->cline = pci->cline;
4528 /* The new instruction has the same pcflow block */
4529 new_pci->pcflow = pci->pcflow;
4531 /* Arrrrg: is pci's previous instruction is a skip, we need to
4532 * change that into a jump (over pci and the new instruction) ... */
4533 if (pcprev && isPCI_SKIP(pcprev))
4535 symbol *lbl = newiTempLabel (NULL);
4536 pCode *label = newpCodeLabel (NULL, lbl->key);
4537 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4539 pCodeInsertAfter (pcprev, jump);
4541 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4542 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4543 switch (PCI(pcprev)->op) {
4548 // These are turned into non-skipping instructions, so
4549 // insert 'BTFSC STATUS, Z' after pcprev
4550 pCodeInsertAfter (pcprev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4553 // no special actions required
4556 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4558 pCodeInsertAfter((pCode*)pci, label);
4562 /*-----------------------------------------------------------------*/
4563 /*-----------------------------------------------------------------*/
4565 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4569 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4571 insertPCodeInstruction(pci, PCI(new_pc));
4574 /*-----------------------------------------------------------------*/
4575 /*-----------------------------------------------------------------*/
4576 static void insertBankSel(pCodeInstruction *pci, const char *name)
4582 // This is a NOP for single-banked devices.
4583 if (pic14_getMaxRam() < 0x80) return;
4585 pcop = popCopyReg(PCOR(pci->pcop));
4586 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4587 if (pcop->name == 0)
4588 pcop->name = strdup(name);
4589 new_pc = newpCode(POC_BANKSEL, pcop);
4591 insertPCodeInstruction(pci, PCI(new_pc));
4594 /*-----------------------------------------------------------------*/
4595 /* If the register is a fixed known addess then we can assign the */
4596 /* bank selection bits. Otherwise the linker is going to assign */
4597 /* the register location and thus has to set bank selection bits */
4598 /* through the banksel directive. */
4599 /* One critical assumption here is that within this C module all */
4600 /* the locally allocated registers are in the same udata sector. */
4601 /* Therefore banksel is only called for external registers or the */
4602 /* first time a local register is encountered. */
4603 /*-----------------------------------------------------------------*/
4604 static int LastRegIdx = -1; /* If the previous register is the same one again then no need to change bank. */
4605 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4608 /* Always insert BANKSELs rather than try to be clever:
4609 * Too many bugs in optimized banksels... */
4610 static PIC_device *pic;
4611 if (!pic) pic = pic14_getPIC();
4613 // possible optimizations:
4614 // * do not emit BANKSELs for SFRs that are present in all banks (bankmsk == regmap for this register)
4615 if (reg && pic && ((reg->alias & pic->bankMask) == pic->bankMask)) return 'L';
4617 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4621 int a = reg->alias>>7;
4623 return cur_bank; // This register is available in all banks
4624 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4625 return cur_bank; // This register is available in banks 0 & 1
4627 if (reg->address&0x80) {
4628 if ((cur_bank==1)||(cur_bank==3)) {
4629 return cur_bank; // This register is available in banks 1 & 3
4632 if ((cur_bank==0)||(cur_bank==1)) {
4633 return cur_bank; // This register is available in banks 0 & 2
4639 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4641 LastRegIdx = reg->rIdx;
4644 /* Optimized code---unfortunately this turns out to be buggy
4645 * (at least on devices with more than two banks). */
4647 bank = REG_BANK(reg);
4648 } else if (reg->isExtern) {
4649 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4651 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4653 if (bank == 'E' || bank == 'L') { // Reg is now extern and linker to assign bank
4654 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4655 } 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
4656 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4657 if (pic14_getMaxRam()&0x100)
4658 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4659 } else { // Current bank and new register banks known - can set bank bits
4660 switch((cur_bank^bank) & 3) {
4664 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4667 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4670 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4671 if (pic14_getMaxRam()&0x100)
4672 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4681 /*-----------------------------------------------------------------*/
4682 /* Check for bank selection pcodes instructions and modify */
4683 /* cur_bank to match. */
4684 /*-----------------------------------------------------------------*/
4685 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4687 if (isSTATUS_REG(reg)) {
4689 if (PCI(pc)->op == POC_BCF) {
4690 int old_bank = *cur_bank;
4691 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4692 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4693 if (*cur_bank & ~(0x3))
4696 *cur_bank = *cur_bank&0x2;
4697 LastRegIdx = reg->rIdx;
4698 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4699 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4700 if (*cur_bank & ~(0x3))
4703 *cur_bank = *cur_bank&0x1;
4704 LastRegIdx = reg->rIdx;
4706 return old_bank != *cur_bank;
4709 if (PCI(pc)->op == POC_BSF) {
4710 int old_bank = *cur_bank;
4711 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4712 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4713 if (*cur_bank & ~(0x3))
4716 *cur_bank = (*cur_bank&0x2) | 0x1;
4717 LastRegIdx = reg->rIdx;
4718 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4719 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4720 if (*cur_bank & ~(0x3))
4723 *cur_bank = (*cur_bank&0x1) | 0x2;
4724 LastRegIdx = reg->rIdx;
4726 return old_bank != *cur_bank;
4729 } else if (PCI(pc)->op == POC_BANKSEL) {
4730 int old_bank = *cur_bank;
4731 regs *r = PCOR(PCI(pc)->pcop)->r;
4732 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4733 LastRegIdx = reg->rIdx;
4734 return old_bank != *cur_bank;
4740 /*-----------------------------------------------------------------*/
4741 /* Set bank selection if necessary */
4742 /*-----------------------------------------------------------------*/
4743 static int DoBankSelect(pCode *pc, int cur_bank) {
4751 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4752 LastRegIdx = -1; /* do not know which register is touched in the called function... */
4753 if (pcf && isPCF(pcf)) {
4755 int rbank = 'U'; // Undetermined
4756 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4757 // Check all the returns to work out what bank is selected
4758 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4760 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4762 rbank = PCI(pcfr)->pcflow->lastBank;
4764 if (rbank != PCI(pcfr)->pcflow->lastBank)
4765 return -1; // Unknown bank - multiple returns with different banks
4770 return -1; // Unknown bank
4772 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4773 /* Extern functions may use registers in different bank - must call banksel */
4774 return -1; /* Unknown bank */
4780 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4781 return -1; /* New bank unknown - linkers choice. */
4784 reg = getRegFromInstruction(pc);
4785 if (!reg && isPCI(pc) &&
4786 ((PCI(pc)->inCond | PCI(pc)->outCond) & PCC_REGISTER))
4788 if (PCI(pc)->pcop && PCI(pc)->pcop->type == PO_IMMEDIATE) {
4789 // fine, this should be low(variable) --> no BANKING required
4791 assert(!"Could not get register from instruction.");
4795 if (IsBankChange(pc,reg,&cur_bank))
4797 if (!isPCI_LIT(pc)) {
4799 /* Examine the instruction before this one to make sure it is
4800 * not a skip type instruction */
4801 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4803 /* This approach does not honor the presence of labels at this instruction... */
4804 //if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4805 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4807 // cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4809 if (!PCI(pc)->pcflow)
4810 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4812 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4818 /*-----------------------------------------------------------------*/
4819 /*-----------------------------------------------------------------*/
4821 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4829 pc = findNextInstruction(pcfl->pc.next);
4831 while(isPCinFlow(pc,PCODE(pcfl))) {
4833 cur_bank = DoBankSelect(pc,cur_bank);
4835 pc = findNextInstruction(pc->next);
4839 if(pcprev && cur_bank) {
4840 // Set bank state to unknown at the end of each flow block
4846 /*-----------------------------------------------------------------*/
4847 /*int compareBankFlow - compare the banking requirements between */
4849 /*-----------------------------------------------------------------*/
4851 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4854 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4857 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4860 if(pcflow->firstBank == -1)
4864 if(pcflowLink->pcflow->firstBank == -1) {
4865 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4866 pcflowLink->pcflow->to :
4867 pcflowLink->pcflow->from);
4868 return compareBankFlow(pcflow, pctl, toORfrom);
4872 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4875 pcflowLink->bank_conflict++;
4876 pcflowLink->pcflow->FromConflicts++;
4877 pcflow->ToConflicts++;
4880 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4883 pcflowLink->bank_conflict++;
4884 pcflowLink->pcflow->ToConflicts++;
4885 pcflow->FromConflicts++;
4889 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4890 pcflowLink->pcflow->pc.seq,
4891 pcflowLink->pcflow->FromConflicts,
4892 pcflowLink->pcflow->ToConflicts);
4898 /*-----------------------------------------------------------------*/
4899 /*-----------------------------------------------------------------*/
4901 void FixBankFlow(pBlock *pb)
4905 pCodeFlowLink *pcfl;
4907 pCode *pcflow_max_To=NULL;
4908 pCode *pcflow_max_From=NULL;
4909 int max_ToConflicts=0;
4910 int max_FromConflicts=0;
4912 /fprintf(stderr,"Fix Bank flow \n");
4913 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4917 First loop through all of the flow objects in this pcode block
4918 and fix the ones that have banking conflicts between the
4922 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4924 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4926 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4928 if(!isPCFL(pcflow)) {
4929 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4933 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4934 PCFL(pcflow)->firstBank >= 0 &&
4935 PCFL(pcflow)->lastBank >= 0 ) {
4937 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4938 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4940 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4941 BanksUsedFlow2(pcflow);
4946 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4948 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4950 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4955 if(!isPCFL(pcflow)) {
4956 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4960 PCFL(pcflow)->FromConflicts = 0;
4961 PCFL(pcflow)->ToConflicts = 0;
4966 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4967 pcfl = setFirstItem(PCFL(pcflow)->from);
4970 pc = PCODE(pcfl->pcflow);
4973 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4974 pc->print(stderr,pc);
4977 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4980 pcfl=setNextItem(PCFL(pcflow)->from);
4983 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4984 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4986 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4987 BanksUsedFlow2(pcflow);
4989 continue; / * Don't need to check the flow from here - it's already been fixed * /
4996 pcfl = setFirstItem(PCFL(pcflow)->to);
4999 pc = PCODE(pcfl->pcflow);
5001 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5002 pc->print(stderr,pc);
5005 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5008 pcfl=setNextItem(PCFL(pcflow)->to);
5011 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5012 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5014 FixRegisterBankingInFlow(PCFL(pcflow),-1);
5015 BanksUsedFlow2(pcflow);
5020 Loop through the flow objects again and find the ones with the
5024 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5026 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
5028 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5029 pcflow_max_To = pcflow;
5031 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5032 pcflow_max_From = pcflow;
5036 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5037 PCFL(pcflow_max_To)->pc.seq,
5038 PCFL(pcflow_max_To)->ToConflicts);
5041 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5042 PCFL(pcflow_max_From)->pc.seq,
5043 PCFL(pcflow_max_From)->FromConflicts);
5048 /*-----------------------------------------------------------------*/
5049 /*-----------------------------------------------------------------*/
5050 void DumpFlow(pBlock *pb)
5054 pCodeFlowLink *pcfl;
5057 fprintf(stderr,"Dump flow \n");
5058 pb->pcHead->print(stderr, pb->pcHead);
5060 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5061 pcflow->print(stderr,pcflow);
5063 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5065 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
5067 if(!isPCFL(pcflow)) {
5068 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5071 fprintf(stderr,"dumping: ");
5072 pcflow->print(stderr,pcflow);
5073 FlowStats(PCFL(pcflow));
5075 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5077 pc = PCODE(pcfl->pcflow);
5079 fprintf(stderr, " from seq %d:\n",pc->seq);
5081 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5082 pc->print(stderr,pc);
5087 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5089 pc = PCODE(pcfl->pcflow);
5091 fprintf(stderr, " to seq %d:\n",pc->seq);
5093 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5094 pc->print(stderr,pc);
5103 /*-----------------------------------------------------------------*/
5104 /*-----------------------------------------------------------------*/
5105 int OptimizepBlock(pBlock *pb)
5110 if(!pb || options.nopeep)
5113 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5115 for(pc = pb->pcHead; pc; pc = pc->next)
5116 matches += pCodePeepMatchRule(pc);
5119 pc = findNextInstruction(pb->pcHead);
5127 if(pCodePeepMatchRule(pc)) {
5132 pc = findNextInstruction(pcprev->next);
5134 pc = findNextInstruction(pb->pcHead);
5136 pc = findNextInstruction(pc->next);
5140 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5145 /*-----------------------------------------------------------------*/
5146 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5147 /*-----------------------------------------------------------------*/
5148 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5152 for(pc = pcs; pc; pc = pc->next) {
5154 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5156 (PCI(pc)->pcop->type == PO_LABEL) &&
5157 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5164 /*-----------------------------------------------------------------*/
5165 /*-----------------------------------------------------------------*/
5166 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5173 (PCI(pc)->pcop->type == PO_LABEL)) {
5175 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5177 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5179 free(pcol->pcop.name);
5181 /* If the key is negative, then we (probably) have a label to
5182 * a function and the name is already defined */
5185 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5189 //sprintf(buffer,"_%05d_DS_",pcl->key);
5191 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5193 pcol->pcop.name = Safe_strdup(s);
5194 pcol->key = pcl->key;
5195 //pc->print(stderr,pc);
5202 /*-----------------------------------------------------------------*/
5203 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5204 /* pCode chain if they're not used. */
5205 /*-----------------------------------------------------------------*/
5206 void pBlockRemoveUnusedLabels(pBlock *pb)
5208 pCode *pc; pCodeLabel *pcl;
5213 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5215 pBranch *pbr = PCI(pc)->label;
5216 if(pbr && pbr->next) {
5217 pCode *pcd = pb->pcHead;
5219 //fprintf(stderr, "multiple labels\n");
5220 //pc->print(stderr,pc);
5225 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5226 //fprintf(stderr,"Used by:\n");
5227 //pcd->print(stderr,pcd);
5229 exchangeLabels(PCL(pbr->pc),pcd);
5238 for(pc = pb->pcHead; pc; pc = pc->next) {
5240 if(isPCL(pc)) // Label pcode
5242 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5243 pcl = PCL(PCI(pc)->label->pc);
5246 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5248 /* This pCode is a label, so search the pBlock to see if anyone
5251 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5252 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5253 /* Couldn't find an instruction that refers to this label
5254 * So, unlink the pCode label from it's pCode chain
5255 * and destroy the label */
5256 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5258 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5259 if(pc->type == PC_LABEL) {
5261 pCodeLabelDestruct(pc);
5263 unlinkpCodeFromBranch(pc, PCODE(pcl));
5264 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5275 /*-----------------------------------------------------------------*/
5276 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5277 /* chain and put them into pBranches that are */
5278 /* associated with the appropriate pCode */
5280 /*-----------------------------------------------------------------*/
5281 void pBlockMergeLabels(pBlock *pb)
5284 pCode *pc, *pcnext=NULL;
5289 /* First, Try to remove any unused labels */
5290 //pBlockRemoveUnusedLabels(pb);
5292 /* Now loop through the pBlock and merge the labels with the opcodes */
5295 // for(pc = pb->pcHead; pc; pc = pc->next) {
5298 pCode *pcn = pc->next;
5300 if(pc->type == PC_LABEL) {
5302 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5303 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5304 if((pcnext = findNextInstruction(pc) )) {
5306 // Unlink the pCode label from it's pCode chain
5309 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5310 // And link it into the instruction's pBranch labels. (Note, since
5311 // it's possible to have multiple labels associated with one instruction
5312 // we must provide a means to accomodate the additional labels. Thus
5313 // the labels are placed into the singly-linked list "label" as
5314 // opposed to being a single member of the pCodeInstruction.)
5316 //_ALLOC(pbr,sizeof(pBranch));
5317 pbr = Safe_calloc(1,sizeof(pBranch));
5321 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5324 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5326 } else if(pc->type == PC_CSOURCE) {
5328 /* merge the source line symbolic info into the next instruction */
5329 if((pcnext = findNextInstruction(pc) )) {
5331 // Unlink the pCode label from it's pCode chain
5333 PCI(pcnext)->cline = PCCS(pc);
5334 //fprintf(stderr, "merging CSRC\n");
5335 //genericPrint(stderr,pcnext);
5341 pBlockRemoveUnusedLabels(pb);
5345 /*-----------------------------------------------------------------*/
5346 /*-----------------------------------------------------------------*/
5347 int OptimizepCode(char dbName)
5349 #define MAX_PASSES 4
5358 DFPRINTF((stderr," Optimizing pCode\n"));
5362 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5363 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5364 matches += OptimizepBlock(pb);
5367 while(matches && ++passes < MAX_PASSES);
5372 /*-----------------------------------------------------------------*/
5373 /* popCopyGPR2Bit - copy a pcode operator */
5374 /*-----------------------------------------------------------------*/
5376 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5380 pcop = newpCodeOpBit(pc->name, bitval, 0);
5382 if( !( (pcop->type == PO_LABEL) ||
5383 (pcop->type == PO_LITERAL) ||
5384 (pcop->type == PO_STR) ))
5385 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5391 /*-----------------------------------------------------------------*/
5392 /*-----------------------------------------------------------------*/
5393 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5396 int firstBank = 'U';
5401 for (pc=pb->pcHead; pc; pc=pc->next) {
5403 firstBank = PCFL(pc)->firstBank;
5407 if (firstBank != 'U') {
5408 /* This block has already been done */
5409 if (firstBank != cur_bank) {
5410 /* This block has started with a different bank - must adjust it */
5411 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5414 regs *reg = getRegFromInstruction(pc);
5416 DoBankSelect(pc,cur_bank);
5426 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5429 for (pc=pb->pcHead; pc; pc=pc->next) {
5431 PCFL(pc)->firstBank = cur_bank;
5434 cur_bank = DoBankSelect(pc,cur_bank);
5437 /* Trace through branches and set the bank selection as required. */
5440 for (pc=pb->pcHead; pc; pc=pc->next) {
5442 PCFL(pc)->firstBank = cur_bank;
5446 if (PCI(pc)->op == POC_GOTO) {
5447 int lastRegIdx = LastRegIdx;
5449 /* Trace through branch */
5450 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5453 regs *reg = getRegFromInstruction(pcl);
5455 int bankUnknown = -1;
5456 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5458 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5464 LastRegIdx = lastRegIdx;
5466 /* Keep track out current bank */
5467 regs *reg = getRegFromInstruction(pc);
5469 IsBankChange(pc,reg,&cur_bank);
5476 /*-----------------------------------------------------------------*/
5477 /*-----------------------------------------------------------------*/
5478 void pBlockDestruct(pBlock *pb)
5489 /*-----------------------------------------------------------------*/
5490 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5491 /* name dbName and combine them */
5492 /* into one block */
5493 /*-----------------------------------------------------------------*/
5494 void mergepBlocks(char dbName)
5497 pBlock *pb, *pbmerged = NULL,*pbn;
5499 pb = the_pFile->pbHead;
5501 //fprintf(stderr," merging blocks named %c\n",dbName);
5505 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5506 if( getpBlock_dbName(pb) == dbName) {
5508 //fprintf(stderr," merged block %c\n",dbName);
5513 addpCode2pBlock(pbmerged, pb->pcHead);
5514 /* addpCode2pBlock doesn't handle the tail: */
5515 pbmerged->pcTail = pb->pcTail;
5517 pb->prev->next = pbn;
5519 pbn->prev = pb->prev;
5524 //printpBlock(stderr, pbmerged);
5531 /*-----------------------------------------------------------------*/
5532 /* AnalyzeFlow - Examine the flow of the code and optimize */
5534 /* level 0 == minimal optimization */
5535 /* optimize registers that are used only by two instructions */
5536 /* level 1 == maximal optimization */
5537 /* optimize by looking at pairs of instructions that use the */
5539 /*-----------------------------------------------------------------*/
5541 void AnalyzeFlow(int level)
5543 static int times_called=0;
5551 /* if this is not the first time this function has been called,
5552 then clean up old flow information */
5553 if(times_called++) {
5554 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5557 RegsUnMapLiveRanges();
5563 /* Phase 2 - Flow Analysis - Register Banking
5565 * In this phase, the individual flow blocks are examined
5566 * and register banking is fixed.
5569 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5570 //FixRegisterBanking(pb);
5572 /* Phase 2 - Flow Analysis
5574 * In this phase, the pCode is partition into pCodeFlow
5575 * blocks. The flow blocks mark the points where a continuous
5576 * stream of instructions changes flow (e.g. because of
5577 * a call or goto or whatever).
5580 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5584 /* Phase 2 - Flow Analysis - linking flow blocks
5586 * In this phase, the individual flow blocks are examined
5587 * to determine their order of excution.
5590 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5593 /* Phase 3 - Flow Analysis - Flow Tree
5595 * In this phase, the individual flow blocks are examined
5596 * to determine their order of excution.
5599 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5603 /* Phase x - Flow Analysis - Used Banks
5605 * In this phase, the individual flow blocks are examined
5606 * to determine the Register Banks they use
5609 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5613 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5614 pCodeRegMapLiveRanges(pb);
5616 RemoveUnusedRegisters();
5618 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5619 pCodeRegOptimizeRegUsage(level);
5624 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5629 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5631 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5632 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5633 pcflow = pcflow->next) {
5635 FillFlow(PCFL(pcflow));
5640 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5642 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5643 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5644 pcflow = pcflow->next) {
5646 FlowStats(PCFL(pcflow));
5652 /*-----------------------------------------------------------------*/
5653 /* AnalyzeBanking - Called after the memory addresses have been */
5654 /* assigned to the registers. */
5656 /*-----------------------------------------------------------------*/
5658 void AnalyzeBanking(void)
5662 if(!picIsInitialized()) {
5663 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5667 if (!the_pFile) return;
5669 /* Phase x - Flow Analysis - Used Banks
5671 * In this phase, the individual flow blocks are examined
5672 * to determine the Register Banks they use
5678 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5679 // BanksUsedFlow(pb);
5680 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5681 FixRegisterBanking(pb,-1); // cur_bank is unknown
5685 /*-----------------------------------------------------------------*/
5686 /*-----------------------------------------------------------------*/
5687 DEFSETFUNC (resetrIdx)
5689 regs *r = (regs *)item;
5697 /*-----------------------------------------------------------------*/
5698 /* InitRegReuse - Initialises variables for code analyzer */
5699 /*-----------------------------------------------------------------*/
5701 void InitReuseReg(void)
5703 /* Find end of statically allocated variables for start idx */
5704 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5705 /* XXX: Avoid clashes with fixed registers, start late. */
5706 unsigned maxIdx = 0x1000;
5708 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5709 if (r->type != REG_SFR) {
5710 maxIdx += r->size; /* Increment for all statically allocated variables */
5714 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5717 /*-----------------------------------------------------------------*/
5718 /*-----------------------------------------------------------------*/
5719 static unsigned register_reassign(pBlock *pb, unsigned idx)
5723 /* check recursion */
5724 pc = setFirstItem(pb->function_entries);
5730 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5732 if (pb->tregisters) {
5734 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5735 if (r->type == REG_GPR) {
5737 if (r->rIdx < (int)idx) {
5740 if (peakIdx < idx) peakIdx = idx;
5741 sprintf(s,"r0x%02X", r->rIdx);
5742 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5744 r->name = Safe_strdup(s);
5750 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5752 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5753 char *dest = get_op_from_instruction(PCI(pc));
5755 pCode *pcn = findFunction(dest);
5757 register_reassign(pcn->pb,idx);
5766 /*------------------------------------------------------------------*/
5767 /* ReuseReg were call tree permits */
5769 /* Re-allocate the GPR for optimum reuse for a given pblock */
5770 /* eg if a function m() calls function f1() and f2(), where f1 */
5771 /* allocates a local variable vf1 and f2 allocates a local */
5772 /* variable vf2. Then providing f1 and f2 do not call each other */
5773 /* they may share the same general purpose registers for vf1 and */
5775 /* This is done by first setting the the regs rIdx to start after */
5776 /* all the global variables, then walking through the call tree */
5777 /* renaming the registers to match their new idx and incrementng */
5778 /* it as it goes. If a function has already been called it will */
5779 /* only rename the registers if it has already used up those */
5780 /* registers ie rIdx of the function's registers is lower than the */
5781 /* current rIdx. That way the register will not be reused while */
5782 /* still being used by an eariler function call. */
5784 /* Note for this to work the functions need to be declared static. */
5786 /*------------------------------------------------------------------*/
5790 if (!the_pFile) return;
5792 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5793 /* Non static functions can be called from other modules so their registers must reassign */
5794 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5795 register_reassign(pb,peakIdx);
5799 /*-----------------------------------------------------------------*/
5800 /* buildCallTree - look at the flow and extract all of the calls */
5802 /*-----------------------------------------------------------------*/
5804 void buildCallTree(void )
5813 /* Now build the call tree.
5814 First we examine all of the pCodes for functions.
5815 Keep in mind that the function boundaries coincide
5816 with pBlock boundaries.
5818 The algorithm goes something like this:
5819 We have two nested loops. The outer loop iterates
5820 through all of the pBlocks/functions. The inner
5821 loop iterates through all of the pCodes for
5822 a given pBlock. When we begin iterating through
5823 a pBlock, the variable pc_fstart, pCode of the start
5824 of a function, is cleared. We then search for pCodes
5825 of type PC_FUNCTION. When one is encountered, we
5826 initialize pc_fstart to this and at the same time
5827 associate a new pBranch object that signifies a
5828 branch entry. If a return is found, then this signifies
5829 a function exit point. We'll link the pCodes of these
5830 returns to the matching pc_fstart.
5832 When we're done, a doubly linked list of pBranches
5833 will exist. The head of this list is stored in
5834 `the_pFile', which is the meta structure for all
5835 of the pCode. Look at the printCallTree function
5836 on how the pBranches are linked together.
5839 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5840 pCode *pc_fstart=NULL;
5841 for(pc = pb->pcHead; pc; pc = pc->next) {
5843 pCodeFunction *pcf = PCF(pc);
5846 if(STRCASECMP(pcf->fname, "_main") == 0) {
5847 //fprintf(stderr," found main \n");
5848 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5852 pbr = Safe_calloc(1,sizeof(pBranch));
5853 pbr->pc = pc_fstart = pc;
5856 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5858 // Here's a better way of doing the same:
5859 addSet(&pb->function_entries, pc);
5862 // Found an exit point in a function, e.g. return
5863 // (Note, there may be more than one return per function)
5865 pBranchLink(PCF(pc_fstart), pcf);
5867 addSet(&pb->function_exits, pc);
5869 } else if(isCALL(pc)) {
5870 addSet(&pb->function_calls,pc);
5876 /*-----------------------------------------------------------------*/
5877 /* AnalyzepCode - parse the pCode that has been generated and form */
5878 /* all of the logical connections. */
5880 /* Essentially what's done here is that the pCode flow is */
5882 /*-----------------------------------------------------------------*/
5884 void AnalyzepCode(char dbName)
5895 /* Phase 1 - Register allocation and peep hole optimization
5897 * The first part of the analysis is to determine the registers
5898 * that are used in the pCode. Once that is done, the peep rules
5899 * are applied to the code. We continue to loop until no more
5900 * peep rule optimizations are found (or until we exceed the
5901 * MAX_PASSES threshold).
5903 * When done, the required registers will be determined.
5909 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5911 /* First, merge the labels with the instructions */
5912 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5913 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5915 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5916 pBlockMergeLabels(pb);
5919 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5923 changes = OptimizepCode(dbName);
5925 } while(changes && (i++ < MAX_PASSES));
5930 /*-----------------------------------------------------------------*/
5931 /* ispCodeFunction - returns true if *pc is the pCode of a */
5933 /*-----------------------------------------------------------------*/
5934 bool ispCodeFunction(pCode *pc)
5937 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5943 /*-----------------------------------------------------------------*/
5944 /* findFunction - Search for a function by name (given the name) */
5945 /* in the set of all functions that are in a pBlock */
5946 /* (note - I expect this to change because I'm planning to limit */
5947 /* pBlock's to just one function declaration */
5948 /*-----------------------------------------------------------------*/
5949 pCode *findFunction(char *fname)
5956 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5958 pc = setFirstItem(pb->function_entries);
5961 if((pc->type == PC_FUNCTION) &&
5963 (strcmp(fname, PCF(pc)->fname)==0))
5966 pc = setNextItem(pb->function_entries);
5974 void MarkUsedRegisters(set *regset)
5979 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5980 r2 = pic14_regWithIdx(r1->rIdx);
5988 void pBlockStats(FILE *of, pBlock *pb)
5994 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5996 // for now just print the first element of each set
5997 pc = setFirstItem(pb->function_entries);
5999 fprintf(of,";entry: ");
6002 pc = setFirstItem(pb->function_exits);
6004 fprintf(of,";has an exit\n");
6008 pc = setFirstItem(pb->function_calls);
6010 fprintf(of,";functions called:\n");
6013 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6014 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
6016 pc = setNextItem(pb->function_calls);
6020 r = setFirstItem(pb->tregisters);
6022 int n = elementsInSet(pb->tregisters);
6024 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6027 fprintf(of,"; %s\n",r->name);
6028 r = setNextItem(pb->tregisters);
6033 /*-----------------------------------------------------------------*/
6034 /*-----------------------------------------------------------------*/
6036 static void sequencepCode(void)
6042 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6044 pb->seq = GpCodeSequenceNumber+1;
6046 for( pc = pb->pcHead; pc; pc = pc->next)
6047 pc->seq = ++GpCodeSequenceNumber;
6053 /*-----------------------------------------------------------------*/
6054 /*-----------------------------------------------------------------*/
6056 set *register_usage(pBlock *pb)
6059 set *registers=NULL;
6060 set *registersInCallPath = NULL;
6062 / * check recursion * /
6064 pc = setFirstItem(pb->function_entries);
6071 if(pc->type != PC_FUNCTION)
6072 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6074 pc = setFirstItem(pb->function_calls);
6075 for( ; pc; pc = setNextItem(pb->function_calls)) {
6077 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6078 char *dest = get_op_from_instruction(PCI(pc));
6080 pcn = findFunction(dest);
6082 registersInCallPath = register_usage(pcn->pb);
6084 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6089 pBlockStats(stderr,pb); // debug
6092 // Mark the registers in this block as used.
6094 MarkUsedRegisters(pb->tregisters);
6095 if(registersInCallPath) {
6096 / * registers were used in the functions this pBlock has called * /
6097 / * so now, we need to see if these collide with the ones we are * /
6100 regs *r1,*r2, *newreg;
6102 DFPRINTF((stderr,"comparing registers\n"));
6104 r1 = setFirstItem(registersInCallPath);
6106 if (r1->type != REG_STK) {
6107 r2 = setFirstItem(pb->tregisters);
6109 while(r2 && (r2->type != REG_STK)) {
6111 if(r2->rIdx == r1->rIdx) {
6112 newreg = pic14_findFreeReg(REG_GPR);
6116 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6120 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6121 r1->rIdx, newreg->rIdx));
6122 r2->rIdx = newreg->rIdx;
6124 r2->name = Safe_strdup(newreg->name);
6128 newreg->wasUsed = 1;
6130 r2 = setNextItem(pb->tregisters);
6134 r1 = setNextItem(registersInCallPath);
6137 / * Collisions have been resolved. Now free the registers in the call path * /
6138 r1 = setFirstItem(registersInCallPath);
6140 newreg = pic14_regWithIdx(r1->rIdx);
6141 if (newreg) newreg->isFree = 1;
6142 r1 = setNextItem(registersInCallPath);
6146 // MarkUsedRegisters(pb->registers);
6148 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6151 DFPRINTF((stderr,"returning regs\n"));
6153 DFPRINTF((stderr,"not returning regs\n"));
6155 DFPRINTF((stderr,"pBlock after register optim.\n"));
6156 pBlockStats(stderr,pb); // debug
6163 /*-----------------------------------------------------------------*/
6164 /* printCallTree - writes the call tree to a file */
6166 /*-----------------------------------------------------------------*/
6167 void pct2(FILE *of,pBlock *pb,int indent)
6171 // set *registersInCallPath = NULL;
6177 return; //recursion ?
6179 pc = setFirstItem(pb->function_entries);
6186 for(i=0;i<indent;i++) // Indentation
6189 if(pc->type == PC_FUNCTION)
6190 fprintf(of,"%s\n",PCF(pc)->fname);
6195 pc = setFirstItem(pb->function_calls);
6196 for( ; pc; pc = setNextItem(pb->function_calls)) {
6198 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6199 char *dest = get_op_from_instruction(PCI(pc));
6201 pcn = findFunction(dest);
6203 pct2(of,pcn->pb,indent+1);
6205 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6213 /*-----------------------------------------------------------------*/
6214 /* printCallTree - writes the call tree to a file */
6216 /*-----------------------------------------------------------------*/
6218 void printCallTree(FILE *of)
6230 fprintf(of, "\npBlock statistics\n");
6231 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6236 fprintf(of,"Call Tree\n");
6237 pbr = the_pFile->functions;
6241 if(!ispCodeFunction(pc))
6242 fprintf(of,"bug in call tree");
6245 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6247 while(pc->next && !ispCodeFunction(pc->next)) {
6249 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6250 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6258 fprintf(of,"\n**************\n\na better call tree\n");
6259 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6264 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6265 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6271 /*-----------------------------------------------------------------*/
6273 /*-----------------------------------------------------------------*/
6275 void InlineFunction(pBlock *pb)
6283 pc = setFirstItem(pb->function_calls);
6285 for( ; pc; pc = setNextItem(pb->function_calls)) {
6288 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6289 pCode *pcp = pc->prev;
6295 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 */
6297 InlineFunction(pcn->pb);
6300 At this point, *pc points to a CALL mnemonic, and
6301 *pcn points to the function that is being called.
6303 To in-line this call, we need to remove the CALL
6304 and RETURN(s), and link the function pCode in with
6311 /* Check if previous instruction was a bit skip */
6312 if (isPCI_BITSKIP(pcp)) {
6314 /* Invert skip instruction and add a goto */
6315 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6317 if(isPCL(pc_call->next)) { // Label pcode
6318 pcl = PCL(pc_call->next);
6319 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6320 pcl = PCL(PCI(pc_call->next)->label->pc);
6322 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6323 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6325 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6328 /* remove callee pBlock from the pBlock linked list */
6329 removepBlock(pcn->pb);
6337 /* Remove the Function pCode */
6338 pct = findNextInstruction(pcn->next);
6340 /* Link the function with the callee */
6341 if (pcp) pcp->next = pcn->next;
6342 pcn->next->prev = pcp;
6344 /* Convert the function name into a label */
6346 pbr = Safe_calloc(1,sizeof(pBranch));
6347 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6349 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6350 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6352 /* turn all of the return's except the last into goto's */
6353 /* check case for 2 instruction pBlocks */
6354 pce = findNextInstruction(pcn->next);
6356 pCode *pce_next = findNextInstruction(pce->next);
6358 if(pce_next == NULL) {
6359 /* found the last return */
6360 pCode *pc_call_next = findNextInstruction(pc_call->next);
6362 //fprintf(stderr,"found last return\n");
6363 //pce->print(stderr,pce);
6364 pce->prev->next = pc_call->next;
6365 pc_call->next->prev = pce->prev;
6366 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6375 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6381 /*-----------------------------------------------------------------*/
6383 /*-----------------------------------------------------------------*/
6385 void InlinepCode(void)
6394 if(!functionInlining)
6397 /* Loop through all of the function definitions and count the
6398 * number of times each one is called */
6399 //fprintf(stderr,"inlining %d\n",__LINE__);
6401 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6403 pc = setFirstItem(pb->function_calls);
6405 for( ; pc; pc = setNextItem(pb->function_calls)) {
6408 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6409 if(pcn && isPCF(pcn)) {
6410 PCF(pcn)->ncalled++;
6413 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6418 //fprintf(stderr,"inlining %d\n",__LINE__);
6420 /* Now, Loop through the function definitions again, but this
6421 * time inline those functions that have only been called once. */
6423 InlineFunction(the_pFile->pbHead);
6424 //fprintf(stderr,"inlining %d\n",__LINE__);
6426 for(pb = the_pFile->pbHead; pb; pb = pb->next)