1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int functionInlining = 1; /* inline functions if nonzero */
79 int debug_verbose = 0; /* Set true to inundate .asm file */
81 // static int GpCodeSequenceNumber = 1;
84 /* statistics (code size estimation) */
85 static unsigned int pcode_insns = 0;
86 static unsigned int pcode_doubles = 0;
89 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
90 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
92 extern void RemoveUnusedRegisters(void);
93 extern void RegsUnMapLiveRanges(void);
94 extern void BuildFlowTree(pBlock *pb);
95 extern void pCodeRegOptimizeRegUsage(int level);
96 extern int picIsInitialized(void);
97 extern const char *pCodeOpType(pCodeOp *pcop);
99 /****************************************************************/
100 /* Forward declarations */
101 /****************************************************************/
103 void unlinkpCode(pCode *pc);
105 static void genericAnalyze(pCode *pc);
106 static void AnalyzeGOTO(pCode *pc);
107 static void AnalyzeSKIP(pCode *pc);
108 static void AnalyzeRETURN(pCode *pc);
111 static void genericDestruct(pCode *pc);
112 static void genericPrint(FILE *of,pCode *pc);
114 static void pCodePrintLabel(FILE *of, pCode *pc);
115 static void pCodePrintFunction(FILE *of, pCode *pc);
116 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
117 static char *get_op_from_instruction( pCodeInstruction *pcc);
118 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
119 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
120 int pCodePeepMatchRule(pCode *pc);
121 void pBlockStats(FILE *of, pBlock *pb);
122 pBlock *newpBlock(void);
123 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
124 void pCodeRegMapLiveRanges(pBlock *pb);
126 pBranch * pBranchAppend(pBranch *h, pBranch *n);
129 /****************************************************************/
130 /* PIC Instructions */
131 /****************************************************************/
133 pCodeInstruction pciADDWF = {
134 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
147 1,0, // dest, bit instruction
149 0, // literal operand
151 (PCC_W | PCC_REGISTER), // inCond
152 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
155 pCodeInstruction pciADDFW = {
156 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
169 0,0, // dest, bit instruction
171 0, // literal operand
173 (PCC_W | PCC_REGISTER), // inCond
174 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
177 pCodeInstruction pciADDLW = {
178 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
191 0,0, // dest, bit instruction
193 1, // literal operand
195 (PCC_W | PCC_LITERAL), // inCond
196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
199 pCodeInstruction pciANDLW = {
200 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
213 0,0, // dest, bit instruction
215 1, // literal operand
217 (PCC_W | PCC_LITERAL), // inCond
218 (PCC_W | PCC_Z) // outCond
221 pCodeInstruction pciANDWF = {
222 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
235 1,0, // dest, bit instruction
237 0, // literal operand
239 (PCC_W | PCC_REGISTER), // inCond
240 (PCC_REGISTER | PCC_Z) // outCond
243 pCodeInstruction pciANDFW = {
244 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
257 0,0, // dest, bit instruction
259 0, // literal operand
261 (PCC_W | PCC_REGISTER), // inCond
262 (PCC_W | PCC_Z) // outCond
265 pCodeInstruction pciBCF = {
266 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
279 1,1, // dest, bit instruction
281 0, // literal operand
283 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
284 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
287 pCodeInstruction pciBSF = {
288 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
301 1,1, // dest, bit instruction
303 0, // literal operand
305 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
306 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
309 pCodeInstruction pciBTFSC = {
310 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
323 0,1, // dest, bit instruction
325 0, // literal operand
327 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
331 pCodeInstruction pciBTFSS = {
332 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
345 0,1, // dest, bit instruction
347 0, // literal operand
349 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
353 pCodeInstruction pciCALL = {
354 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
367 0,0, // dest, bit instruction
369 0, // literal operand
371 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
372 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
375 pCodeInstruction pciCOMF = {
376 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
389 1,0, // dest, bit instruction
391 0, // literal operand
393 PCC_REGISTER, // inCond
394 PCC_REGISTER | PCC_Z // outCond
397 pCodeInstruction pciCOMFW = {
398 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
411 0,0, // dest, bit instruction
413 0, // literal operand
415 PCC_REGISTER, // inCond
416 PCC_W | PCC_Z // outCond
419 pCodeInstruction pciCLRF = {
420 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
433 0,0, // dest, bit instruction
435 0, // literal operand
438 PCC_REGISTER | PCC_Z // outCond
441 pCodeInstruction pciCLRW = {
442 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
455 0,0, // dest, bit instruction
457 0, // literal operand
460 PCC_W | PCC_Z // outCond
463 pCodeInstruction pciCLRWDT = {
464 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
477 0,0, // dest, bit instruction
479 0, // literal operand
485 pCodeInstruction pciDECF = {
486 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
499 1,0, // dest, bit instruction
501 0, // literal operand
503 PCC_REGISTER, // inCond
504 PCC_REGISTER | PCC_Z // outCond
507 pCodeInstruction pciDECFW = {
508 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
521 0,0, // dest, bit instruction
523 0, // literal operand
525 PCC_REGISTER, // inCond
526 PCC_W | PCC_Z // outCond
529 pCodeInstruction pciDECFSZ = {
530 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
543 1,0, // dest, bit instruction
545 0, // literal operand
547 PCC_REGISTER, // inCond
548 PCC_REGISTER // outCond
551 pCodeInstruction pciDECFSZW = {
552 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
565 0,0, // dest, bit instruction
567 0, // literal operand
569 PCC_REGISTER, // inCond
573 pCodeInstruction pciGOTO = {
574 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
587 0,0, // dest, bit instruction
589 0, // literal operand
595 pCodeInstruction pciINCF = {
596 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
609 1,0, // dest, bit instruction
611 0, // literal operand
613 PCC_REGISTER, // inCond
614 PCC_REGISTER | PCC_Z // outCond
617 pCodeInstruction pciINCFW = {
618 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
631 0,0, // dest, bit instruction
633 0, // literal operand
635 PCC_REGISTER, // inCond
636 PCC_W | PCC_Z // outCond
639 pCodeInstruction pciINCFSZ = {
640 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
653 1,0, // dest, bit instruction
655 0, // literal operand
657 PCC_REGISTER, // inCond
658 PCC_REGISTER // outCond
661 pCodeInstruction pciINCFSZW = {
662 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
675 0,0, // dest, bit instruction
677 0, // literal operand
679 PCC_REGISTER, // inCond
683 pCodeInstruction pciIORWF = {
684 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
697 1,0, // dest, bit instruction
699 0, // literal operand
701 (PCC_W | PCC_REGISTER), // inCond
702 (PCC_REGISTER | PCC_Z) // outCond
705 pCodeInstruction pciIORFW = {
706 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
719 0,0, // dest, bit instruction
721 0, // literal operand
723 (PCC_W | PCC_REGISTER), // inCond
724 (PCC_W | PCC_Z) // outCond
727 pCodeInstruction pciIORLW = {
728 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
741 0,0, // dest, bit instruction
743 1, // literal operand
745 (PCC_W | PCC_LITERAL), // inCond
746 (PCC_W | PCC_Z) // outCond
749 pCodeInstruction pciMOVF = {
750 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
763 1,0, // dest, bit instruction
765 0, // literal operand
767 PCC_REGISTER, // inCond
771 pCodeInstruction pciMOVFW = {
772 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
785 0,0, // dest, bit instruction
787 0, // literal operand
789 PCC_REGISTER, // inCond
790 (PCC_W | PCC_Z) // outCond
793 pCodeInstruction pciMOVWF = {
794 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
807 0,0, // dest, bit instruction
809 0, // literal operand
812 PCC_REGISTER // outCond
815 pCodeInstruction pciMOVLW = {
816 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
828 0,0, // dest, bit instruction
830 1, // literal operand
832 (PCC_NONE | PCC_LITERAL), // inCond
836 pCodeInstruction pciNOP = {
837 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
849 0,0, // dest, bit instruction
851 0, // literal operand
857 pCodeInstruction pciRETFIE = {
858 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
871 0,0, // dest, bit instruction
873 0, // literal operand
876 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
879 pCodeInstruction pciRETLW = {
880 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
893 0,0, // dest, bit instruction
895 1, // literal operand
897 PCC_LITERAL, // inCond
898 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
901 pCodeInstruction pciRETURN = {
902 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
915 0,0, // dest, bit instruction
917 0, // literal operand
919 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
920 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
923 pCodeInstruction pciRLF = {
924 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
937 1,0, // dest, bit instruction
939 0, // literal operand
941 (PCC_C | PCC_REGISTER), // inCond
942 (PCC_REGISTER | PCC_C ) // outCond
945 pCodeInstruction pciRLFW = {
946 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
959 0,0, // dest, bit instruction
961 0, // literal operand
963 (PCC_C | PCC_REGISTER), // inCond
964 (PCC_W | PCC_C) // outCond
967 pCodeInstruction pciRRF = {
968 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
981 1,0, // dest, bit instruction
983 0, // literal operand
985 (PCC_C | PCC_REGISTER), // inCond
986 (PCC_REGISTER | PCC_C) // outCond
989 pCodeInstruction pciRRFW = {
990 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1003 0,0, // dest, bit instruction
1004 0,0, // branch, skip
1005 0, // literal operand
1007 (PCC_C | PCC_REGISTER), // inCond
1008 (PCC_W | PCC_C) // outCond
1011 pCodeInstruction pciSUBWF = {
1012 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1018 NULL, // from branch
1025 1,0, // dest, bit instruction
1026 0,0, // branch, skip
1027 0, // literal operand
1029 (PCC_W | PCC_REGISTER), // inCond
1030 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1033 pCodeInstruction pciSUBFW = {
1034 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1040 NULL, // from branch
1047 0,0, // dest, bit instruction
1048 0,0, // branch, skip
1049 0, // literal operand
1051 (PCC_W | PCC_REGISTER), // inCond
1052 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1055 pCodeInstruction pciSUBLW = {
1056 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1062 NULL, // from branch
1069 0,0, // dest, bit instruction
1070 0,0, // branch, skip
1071 1, // literal operand
1073 (PCC_W | PCC_LITERAL), // inCond
1074 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1077 pCodeInstruction pciSWAPF = {
1078 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1084 NULL, // from branch
1091 1,0, // dest, bit instruction
1092 0,0, // branch, skip
1093 0, // literal operand
1095 (PCC_REGISTER), // inCond
1096 (PCC_REGISTER) // outCond
1099 pCodeInstruction pciSWAPFW = {
1100 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1106 NULL, // from branch
1113 0,0, // dest, bit instruction
1114 0,0, // branch, skip
1115 0, // literal operand
1117 (PCC_REGISTER), // inCond
1121 pCodeInstruction pciTRIS = {
1122 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1128 NULL, // from branch
1135 0,0, // dest, bit instruction
1136 0,0, // branch, skip
1137 0, // literal operand
1139 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1140 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1143 pCodeInstruction pciXORWF = {
1144 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1150 NULL, // from branch
1157 1,0, // dest, bit instruction
1158 0,0, // branch, skip
1159 0, // literal operand
1161 (PCC_W | PCC_REGISTER), // inCond
1162 (PCC_REGISTER | PCC_Z) // outCond
1165 pCodeInstruction pciXORFW = {
1166 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1172 NULL, // from branch
1179 0,0, // dest, bit instruction
1180 0,0, // branch, skip
1181 0, // literal operand
1183 (PCC_W | PCC_REGISTER), // inCond
1184 (PCC_W | PCC_Z) // outCond
1187 pCodeInstruction pciXORLW = {
1188 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1194 NULL, // from branch
1201 0,0, // dest, bit instruction
1202 0,0, // branch, skip
1203 1, // literal operand
1205 (PCC_W | PCC_LITERAL), // inCond
1206 (PCC_W | PCC_Z) // outCond
1210 pCodeInstruction pciBANKSEL = {
1211 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1217 NULL, // from branch
1224 0,0, // dest, bit instruction
1225 0,0, // branch, skip
1226 0, // literal operand
1232 pCodeInstruction pciPAGESEL = {
1233 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1239 NULL, // from branch
1246 0,0, // dest, bit instruction
1247 0,0, // branch, skip
1248 0, // literal operand
1254 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1257 /*-----------------------------------------------------------------*/
1258 /* return a unique ID number to assist pCodes debuging */
1259 /*-----------------------------------------------------------------*/
1260 unsigned PCodeID(void) {
1261 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1263 static unsigned int stop;
1264 if (pcodeId == 1448)
1265 stop++; // Place break point here
1270 #ifdef HAVE_VSNPRINTF
1271 // Alas, vsnprintf is not ANSI standard, and does not exist
1272 // on Solaris (and probably other non-Gnu flavored Unixes).
1274 /*-----------------------------------------------------------------*/
1275 /* SAFE_snprintf - like snprintf except the string pointer is */
1276 /* after the string has been printed to. This is */
1277 /* useful for printing to string as though if it */
1278 /* were a stream. */
1279 /*-----------------------------------------------------------------*/
1280 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1288 va_start(val, format);
1290 vsnprintf(*str, *size, format, val);
1295 if((size_t)len > *size) {
1296 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1297 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1305 #else // HAVE_VSNPRINTF
1307 // This version is *not* safe, despite the name.
1309 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1313 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1318 va_start(val, format);
1320 vsprintf(buffer, format, val);
1323 len = strlen(buffer);
1325 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1326 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1329 strcpy(*str, buffer);
1335 #endif // HAVE_VSNPRINTF
1338 extern void initStack(int base_address, int size);
1339 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1340 extern regs *allocInternalRegister(int rIdx, char * name, short 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 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1354 if ((unsigned)shareBankAddress > getMaxRam()) /* If total RAM is less than 0x7f as with 16f84 then reduce shareBankAddress to fit */
1355 shareBankAddress = (int)getMaxRam();
1356 stkSize = 15; /* Set pseudo stack size to 15, on multi memory bank ICs this leaves room for WSAVE (used for interrupts) to fit into the shared portion of the memory bank */
1357 initStack(shareBankAddress, stkSize); /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1359 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1360 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1361 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1362 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1363 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1364 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1366 pc_status.rIdx = IDX_STATUS;
1367 pc_fsr.rIdx = IDX_FSR;
1368 pc_indf.rIdx = IDX_INDF;
1369 pc_intcon.rIdx = IDX_INTCON;
1370 pc_pcl.rIdx = IDX_PCL;
1371 pc_pclath.rIdx = IDX_PCLATH;
1373 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. */
1374 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1375 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1377 pc_wsave.rIdx = pc_wsave.r->rIdx;
1378 pc_ssave.rIdx = pc_ssave.r->rIdx;
1379 pc_psave.rIdx = pc_psave.r->rIdx;
1381 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1382 pc_wsave.r->address = shareBankAddress-stkSize;
1383 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1384 pc_ssave.r->address = shareBankAddress-stkSize-1;
1385 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1386 pc_psave.r->address = shareBankAddress-stkSize-2;
1388 /* probably should put this in a separate initialization routine */
1389 pb_dead_pcodes = newpBlock();
1393 /*-----------------------------------------------------------------*/
1394 /* mnem2key - convert a pic mnemonic into a hash key */
1395 /* (BTW - this spreads the mnemonics quite well) */
1397 /*-----------------------------------------------------------------*/
1399 int mnem2key(unsigned char const *mnem)
1408 key += toupper(*mnem++) +1;
1412 return (key & 0x1f);
1416 void pic14initMnemonics(void)
1421 pCodeInstruction *pci;
1423 if(mnemonics_initialized)
1426 //FIXME - probably should NULL out the array before making the assignments
1427 //since we check the array contents below this initialization.
1429 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1430 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1431 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1432 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1433 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1434 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1435 pic14Mnemonics[POC_BCF] = &pciBCF;
1436 pic14Mnemonics[POC_BSF] = &pciBSF;
1437 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1438 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1439 pic14Mnemonics[POC_CALL] = &pciCALL;
1440 pic14Mnemonics[POC_COMF] = &pciCOMF;
1441 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1442 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1443 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1444 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1445 pic14Mnemonics[POC_DECF] = &pciDECF;
1446 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1447 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1448 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1449 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1450 pic14Mnemonics[POC_INCF] = &pciINCF;
1451 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1452 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1453 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1454 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1455 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1456 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1457 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1458 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1459 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1460 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1461 pic14Mnemonics[POC_NOP] = &pciNOP;
1462 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1463 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1464 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1465 pic14Mnemonics[POC_RLF] = &pciRLF;
1466 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1467 pic14Mnemonics[POC_RRF] = &pciRRF;
1468 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1469 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1470 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1471 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1472 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1473 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1474 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1475 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1476 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1477 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1478 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1479 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1481 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1482 if(pic14Mnemonics[i])
1483 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1484 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1487 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1488 pci = hTabNextItem(pic14MnemonicsHash, &key);
1491 mnemonics_initialized = 1;
1494 int getpCodePeepCommand(char *cmd);
1496 int getpCode(char *mnem,unsigned dest)
1499 pCodeInstruction *pci;
1500 int key = mnem2key(mnem);
1502 if(!mnemonics_initialized)
1503 pic14initMnemonics();
1505 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1509 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1510 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1514 pci = hTabNextItemWK (pic14MnemonicsHash);
1521 /*-----------------------------------------------------------------*
1522 * pic14initpCodePeepCommands
1524 *-----------------------------------------------------------------*/
1525 void pic14initpCodePeepCommands(void)
1533 hTabAddItem(&pic14pCodePeepCommandsHash,
1534 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1536 } while (peepCommands[i].cmd);
1538 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1541 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1542 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1547 /*-----------------------------------------------------------------
1550 *-----------------------------------------------------------------*/
1552 int getpCodePeepCommand(char *cmd)
1556 int key = mnem2key(cmd);
1559 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1562 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1563 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1567 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1574 char getpBlock_dbName(pBlock *pb)
1580 return pb->cmemmap->dbName;
1584 void pBlockConvert2ISR(pBlock *pb)
1595 /*-----------------------------------------------------------------*/
1596 /* movepBlock2Head - given the dbname of a pBlock, move all */
1597 /* instances to the front of the doubly linked */
1598 /* list of pBlocks */
1599 /*-----------------------------------------------------------------*/
1601 void movepBlock2Head(char dbName)
1608 pb = the_pFile->pbHead;
1612 if(getpBlock_dbName(pb) == dbName) {
1613 pBlock *pbn = pb->next;
1614 pb->next = the_pFile->pbHead;
1615 the_pFile->pbHead->prev = pb;
1616 the_pFile->pbHead = pb;
1619 pb->prev->next = pbn;
1621 // If the pBlock that we just moved was the last
1622 // one in the link of all of the pBlocks, then we
1623 // need to point the tail to the block just before
1624 // the one we moved.
1625 // Note: if pb->next is NULL, then pb must have
1626 // been the last pBlock in the chain.
1629 pbn->prev = pb->prev;
1631 the_pFile->pbTail = pb->prev;
1642 void copypCode(FILE *of, char dbName)
1646 if(!of || !the_pFile)
1649 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1650 if(getpBlock_dbName(pb) == dbName) {
1659 void resetpCodeStatistics (void)
1661 pcode_insns = pcode_doubles = 0;
1664 void dumppCodeStatistics (FILE *of)
1666 /* dump statistics */
1668 fprintf (of, ";\tcode size estimation:\n");
1669 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1673 void pcode_test(void)
1676 DFPRINTF((stderr,"pcode is alive!\n"));
1686 /* create the file name */
1687 strcpy(buffer,dstFileName);
1688 strcat(buffer,".p");
1690 if( !(pFile = fopen(buffer, "w" ))) {
1691 werror(E_FILE_OPEN_ERR,buffer);
1695 fprintf(pFile,"pcode dump\n\n");
1697 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1698 fprintf(pFile,"\n\tNew pBlock\n\n");
1700 fprintf(pFile,"%s",pb->cmemmap->sname);
1702 fprintf(pFile,"internal pblock");
1704 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1705 printpBlock(pFile,pb);
1709 /*-----------------------------------------------------------------*/
1710 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1711 /* ister, RegCond will return the bit being referenced. */
1713 /* fixme - why not just OR in the pcop bit field */
1714 /*-----------------------------------------------------------------*/
1716 static int RegCond(pCodeOp *pcop)
1722 if (pcop->type == PO_GPR_BIT) {
1723 char *name = pcop->name;
1725 name = PCOR(pcop)->r->name;
1726 if (strcmp(name, pc_status.pcop.name) == 0)
1728 switch(PCORB(pcop)->bit) {
1742 /*-----------------------------------------------------------------*/
1743 /* newpCode - create and return a newly initialized pCode */
1745 /* fixme - rename this */
1747 /* The purpose of this routine is to create a new Instruction */
1748 /* pCode. This is called by gen.c while the assembly code is being */
1752 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1753 /* (note that the op is analogous to but not the */
1754 /* same thing as the opcode of the instruction.) */
1755 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1758 /* a pointer to the new malloc'd pCode is returned. */
1762 /*-----------------------------------------------------------------*/
1763 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1765 pCodeInstruction *pci ;
1767 if(!mnemonics_initialized)
1768 pic14initMnemonics();
1770 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1772 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1773 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1774 pci->pc.id = PCodeID();
1777 if(pci->inCond & PCC_EXAMINE_PCOP)
1778 pci->inCond |= RegCond(pcop);
1780 if(pci->outCond & PCC_EXAMINE_PCOP)
1781 pci->outCond |= RegCond(pcop);
1783 pci->pc.prev = pci->pc.next = NULL;
1784 return (pCode *)pci;
1787 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1793 /*-----------------------------------------------------------------*/
1794 /* newpCodeWild - create a "wild" as in wild card pCode */
1796 /* Wild pcodes are used during the peep hole optimizer to serve */
1797 /* as place holders for any instruction. When a snippet of code is */
1798 /* compared to a peep hole rule, the wild card opcode will match */
1799 /* any instruction. However, the optional operand and label are */
1800 /* additional qualifiers that must also be matched before the */
1801 /* line (of assembly code) is declared matched. Note that the */
1802 /* operand may be wild too. */
1804 /* Note, a wild instruction is specified just like a wild var: */
1805 /* %4 ; A wild instruction, */
1806 /* See the peeph.def file for additional examples */
1808 /*-----------------------------------------------------------------*/
1810 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1815 pcw = Safe_calloc(1,sizeof(pCodeWild));
1817 pcw->pci.pc.type = PC_WILD;
1818 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1819 pcw->id = PCodeID();
1820 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1821 pcw->pci.pc.pb = NULL;
1823 // pcw->pci.pc.analyze = genericAnalyze;
1824 pcw->pci.pc.destruct = genericDestruct;
1825 pcw->pci.pc.print = genericPrint;
1827 pcw->id = pCodeID; // this is the 'n' in %n
1828 pcw->operand = optional_operand;
1829 pcw->label = optional_label;
1831 pcw->mustBeBitSkipInst = 0;
1832 pcw->mustNotBeBitSkipInst = 0;
1833 pcw->invertBitSkipInst = 0;
1835 return ( (pCode *)pcw);
1839 /*-----------------------------------------------------------------*/
1840 /* newPcodeInlineP - create a new pCode from a char string */
1841 /*-----------------------------------------------------------------*/
1844 pCode *newpCodeInlineP(char *cP)
1849 pcc = Safe_calloc(1,sizeof(pCodeComment));
1851 pcc->pc.type = PC_INLINE;
1852 pcc->pc.prev = pcc->pc.next = NULL;
1853 pcc->pc.id = PCodeID();
1854 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1857 // pcc->pc.analyze = genericAnalyze;
1858 pcc->pc.destruct = genericDestruct;
1859 pcc->pc.print = genericPrint;
1862 pcc->comment = Safe_strdup(cP);
1864 pcc->comment = NULL;
1866 return ( (pCode *)pcc);
1870 /*-----------------------------------------------------------------*/
1871 /* newPcodeCharP - create a new pCode from a char string */
1872 /*-----------------------------------------------------------------*/
1874 pCode *newpCodeCharP(char *cP)
1879 pcc = Safe_calloc(1,sizeof(pCodeComment));
1881 pcc->pc.type = PC_COMMENT;
1882 pcc->pc.prev = pcc->pc.next = NULL;
1883 pcc->pc.id = PCodeID();
1884 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1887 // pcc->pc.analyze = genericAnalyze;
1888 pcc->pc.destruct = genericDestruct;
1889 pcc->pc.print = genericPrint;
1892 pcc->comment = Safe_strdup(cP);
1894 pcc->comment = NULL;
1896 return ( (pCode *)pcc);
1900 /*-----------------------------------------------------------------*/
1901 /* newpCodeFunction - */
1902 /*-----------------------------------------------------------------*/
1905 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1909 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1910 //_ALLOC(pcf,sizeof(pCodeFunction));
1912 pcf->pc.type = PC_FUNCTION;
1913 pcf->pc.prev = pcf->pc.next = NULL;
1914 pcf->pc.id = PCodeID();
1915 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1918 // pcf->pc.analyze = genericAnalyze;
1919 pcf->pc.destruct = genericDestruct;
1920 pcf->pc.print = pCodePrintFunction;
1925 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1926 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1927 strcpy(pcf->modname,mod);
1929 pcf->modname = NULL;
1932 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1933 pcf->fname = Safe_calloc(1,strlen(f)+1);
1934 strcpy(pcf->fname,f);
1938 pcf->isPublic = (unsigned)isPublic;
1940 return ( (pCode *)pcf);
1944 /*-----------------------------------------------------------------*/
1946 /*-----------------------------------------------------------------*/
1947 void destructpCodeFlow(pCode *pc)
1949 if(!pc || !isPCFL(pc))
1958 deleteSet(&PCFL(pc)->registers);
1959 deleteSet(&PCFL(pc)->from);
1960 deleteSet(&PCFL(pc)->to);
1965 pCode *newpCodeFlow(void )
1969 //_ALLOC(pcflow,sizeof(pCodeFlow));
1970 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1972 pcflow->pc.type = PC_FLOW;
1973 pcflow->pc.prev = pcflow->pc.next = NULL;
1974 pcflow->pc.pb = NULL;
1976 // pcflow->pc.analyze = genericAnalyze;
1977 pcflow->pc.destruct = destructpCodeFlow;
1978 pcflow->pc.print = genericPrint;
1980 pcflow->pc.seq = GpcFlowSeq++;
1982 pcflow->from = pcflow->to = NULL;
1984 pcflow->inCond = PCC_NONE;
1985 pcflow->outCond = PCC_NONE;
1987 pcflow->firstBank = 'U'; /* Undetermined */
1988 pcflow->lastBank = 'U'; /* Undetermined */
1990 pcflow->FromConflicts = 0;
1991 pcflow->ToConflicts = 0;
1995 pcflow->registers = newSet();
1997 return ( (pCode *)pcflow);
2001 /*-----------------------------------------------------------------*/
2002 /*-----------------------------------------------------------------*/
2003 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2005 pCodeFlowLink *pcflowLink;
2007 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2009 pcflowLink->pcflow = pcflow;
2010 pcflowLink->bank_conflict = 0;
2015 /*-----------------------------------------------------------------*/
2016 /* newpCodeCSource - create a new pCode Source Symbol */
2017 /*-----------------------------------------------------------------*/
2019 pCode *newpCodeCSource(int ln, char *f, const char *l)
2024 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2026 pccs->pc.type = PC_CSOURCE;
2027 pccs->pc.prev = pccs->pc.next = NULL;
2028 pccs->pc.id = PCodeID();
2031 pccs->pc.destruct = genericDestruct;
2032 pccs->pc.print = genericPrint;
2034 pccs->line_number = ln;
2036 pccs->line = Safe_strdup(l);
2041 pccs->file_name = Safe_strdup(f);
2043 pccs->file_name = NULL;
2045 return ( (pCode *)pccs);
2049 /*******************************************************************/
2050 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2051 /* added by VR 6-Jun-2003 */
2052 /*******************************************************************/
2054 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2061 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2062 pcad->pci.pc.type = PC_ASMDIR;
2063 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2064 pcad->pci.pc.pb = NULL;
2065 pcad->pci.pc.destruct = genericDestruct;
2066 pcad->pci.pc.print = genericPrint;
2068 if(asdir && *asdir) {
2070 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2072 pcad->directive = Safe_strdup( asdir );
2075 va_start(ap, argfmt);
2077 memset(buffer, 0, sizeof(buffer));
2078 if(argfmt && *argfmt)
2079 vsprintf(buffer, argfmt, ap);
2083 while(isspace((unsigned char)*lbp))lbp++;
2086 pcad->arg = Safe_strdup( lbp );
2088 return ((pCode *)pcad);
2091 /*-----------------------------------------------------------------*/
2092 /* pCodeLabelDestruct - free memory used by a label. */
2093 /*-----------------------------------------------------------------*/
2094 static void pCodeLabelDestruct(pCode *pc)
2100 if((pc->type == PC_LABEL) && PCL(pc)->label)
2101 free(PCL(pc)->label);
2107 pCode *newpCodeLabel(char *name, int key)
2113 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2115 pcl->pc.type = PC_LABEL;
2116 pcl->pc.prev = pcl->pc.next = NULL;
2117 pcl->pc.id = PCodeID();
2118 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2121 // pcl->pc.analyze = genericAnalyze;
2122 pcl->pc.destruct = pCodeLabelDestruct;
2123 pcl->pc.print = pCodePrintLabel;
2129 sprintf(s,"_%05d_DS_",key);
2134 pcl->label = Safe_strdup(s);
2136 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2137 return ( (pCode *)pcl);
2142 /*-----------------------------------------------------------------*/
2143 /* newpBlock - create and return a pointer to a new pBlock */
2144 /*-----------------------------------------------------------------*/
2145 pBlock *newpBlock(void)
2150 PpB = Safe_calloc(1,sizeof(pBlock) );
2151 PpB->next = PpB->prev = NULL;
2153 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2154 PpB->tregisters = NULL;
2156 PpB->FlowTree = NULL;
2162 /*-----------------------------------------------------------------*/
2163 /* newpCodeChain - create a new chain of pCodes */
2164 /*-----------------------------------------------------------------*
2166 * This function will create a new pBlock and the pointer to the
2167 * pCode that is passed in will be the first pCode in the block.
2168 *-----------------------------------------------------------------*/
2171 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2174 pBlock *pB = newpBlock();
2176 pB->pcHead = pB->pcTail = pc;
2183 /*-----------------------------------------------------------------*/
2184 /* newpCodeOpLabel - Create a new label given the key */
2185 /* Note, a negative key means that the label is part of wild card */
2186 /* (and hence a wild card label) used in the pCodePeep */
2187 /* optimizations). */
2188 /*-----------------------------------------------------------------*/
2190 pCodeOp *newpCodeOpLabel(char *name, int key)
2193 static int label_key=-1;
2197 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2198 pcop->type = PO_LABEL;
2203 sprintf(s=buffer,"_%05d_DS_",key);
2205 s = name, key = label_key--;
2207 PCOLAB(pcop)->offset = 0;
2209 pcop->name = Safe_strdup(s);
2211 ((pCodeOpLabel *)pcop)->key = key;
2213 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2217 /*-----------------------------------------------------------------*/
2218 /*-----------------------------------------------------------------*/
2219 pCodeOp *newpCodeOpLit(int lit)
2225 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2226 pcop->type = PO_LITERAL;
2230 sprintf(s,"0x%02x", (unsigned char)lit);
2232 pcop->name = Safe_strdup(s);
2235 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2240 /*-----------------------------------------------------------------*/
2241 /*-----------------------------------------------------------------*/
2242 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2246 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2247 pcop->type = PO_IMMEDIATE;
2250 pcop->name = Safe_strdup(name);
2253 r = dirregWithName(name);
2257 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2258 PCOI(pcop)->rIdx = r->rIdx;
2260 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2261 PCOI(pcop)->rIdx = -1;
2263 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2268 PCOI(pcop)->index = index;
2269 PCOI(pcop)->offset = offset;
2270 PCOI(pcop)->_const = code_space;
2271 PCOI(pcop)->_function = is_func;
2276 /*-----------------------------------------------------------------*/
2277 /*-----------------------------------------------------------------*/
2278 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2284 if(!pcwb || !subtype) {
2285 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2289 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2290 pcop->type = PO_WILD;
2291 sprintf(s,"%%%d",id);
2292 pcop->name = Safe_strdup(s);
2294 PCOW(pcop)->id = id;
2295 PCOW(pcop)->pcwb = pcwb;
2296 PCOW(pcop)->subtype = subtype;
2297 PCOW(pcop)->matched = NULL;
2301 /*-----------------------------------------------------------------*/
2302 /* Find a symbol with matching name */
2303 /*-----------------------------------------------------------------*/
2304 static symbol *symFindWithName(memmap * map, const char *name)
2308 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2309 if (sym->rname && (strcmp(sym->rname,name)==0))
2315 /*-----------------------------------------------------------------*/
2316 /*-----------------------------------------------------------------*/
2317 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2322 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2323 pcop->type = PO_GPR_BIT;
2325 PCORB(pcop)->bit = ibit;
2326 PCORB(pcop)->inBitSpace = inBitSpace;
2328 if (name) r = regFindWithName(name);
2330 // Register has not been allocated - check for symbol information
2332 sym = symFindWithName(bit, name);
2333 if (!sym) sym = symFindWithName(sfrbit, name);
2334 if (!sym) sym = symFindWithName(sfr, name);
2336 r = allocNewDirReg(sym->etype,name);
2342 PCOR(pcop)->rIdx = r->rIdx;
2344 pcop->name = Safe_strdup(name);
2345 PCOR(pcop)->r = NULL;
2346 PCOR(pcop)->rIdx = 0;
2351 /*-----------------------------------------------------------------*
2352 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2354 * If rIdx >=0 then a specific register from the set of registers
2355 * will be selected. If rIdx <0, then a new register will be searched
2357 *-----------------------------------------------------------------*/
2359 pCodeOp *newpCodeOpReg(int rIdx)
2363 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2368 PCOR(pcop)->rIdx = rIdx;
2369 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2371 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2374 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2378 pcop->type = PCOR(pcop)->r->pc_type;
2383 pCodeOp *newpCodeOpRegFromStr(char *name)
2387 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2388 PCOR(pcop)->r = allocRegByName(name, 1);
2389 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2390 pcop->type = PCOR(pcop)->r->pc_type;
2391 pcop->name = PCOR(pcop)->r->name;
2396 pCodeOp *newpCodeOpStr(char *name)
2400 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2401 pcop->type = PO_STR;
2402 pcop->name = Safe_strdup(name);
2404 PCOS(pcop)->isPublic = 0;
2410 /*-----------------------------------------------------------------*/
2411 /*-----------------------------------------------------------------*/
2413 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2420 pcop = newpCodeOpBit(name, -1,0);
2424 pcop = newpCodeOpLit(-1);
2428 pcop = newpCodeOpLabel(NULL,-1);
2432 pcop = newpCodeOpReg(-1);
2435 case PO_GPR_POINTER:
2436 case PO_GPR_REGISTER:
2438 pcop = newpCodeOpRegFromStr(name);
2440 pcop = newpCodeOpReg(-1);
2444 pcop = newpCodeOpStr(name);
2448 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2451 pcop->name = Safe_strdup(name);
2459 /*-----------------------------------------------------------------*/
2460 /*-----------------------------------------------------------------*/
2461 void pCodeConstString(char *name, char *value)
2466 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2471 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2475 sprintf(buffer,"; %s = %s",name,value);
2476 for (i=strlen(buffer); i--; ) {
2477 unsigned char c = buffer[i];
2478 if (c=='\r' || c=='\n') {
2479 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2481 if (c=='\r') buffer[i+1] = 'r';
2482 else if (c=='\n') buffer[i+1] = 'n';
2486 addpCode2pBlock(pb,newpCodeCharP(buffer));
2487 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2490 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2496 /*-----------------------------------------------------------------*/
2497 /*-----------------------------------------------------------------*/
2498 void pCodeReadCodeTable(void)
2502 fprintf(stderr, " %s\n",__FUNCTION__);
2504 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2508 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2509 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2510 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2511 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2513 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2514 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2515 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2516 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2521 /*-----------------------------------------------------------------*/
2522 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2523 /*-----------------------------------------------------------------*/
2524 void addpCode2pBlock(pBlock *pb, pCode *pc)
2531 /* If this is the first pcode to be added to a block that
2532 * was initialized with a NULL pcode, then go ahead and
2533 * make this pcode the head and tail */
2534 pb->pcHead = pb->pcTail = pc;
2537 pb->pcTail->next = pc;
2539 pc->prev = pb->pcTail;
2546 /*-----------------------------------------------------------------*/
2547 /* addpBlock - place a pBlock into the pFile */
2548 /*-----------------------------------------------------------------*/
2549 void addpBlock(pBlock *pb)
2551 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2554 /* First time called, we'll pass through here. */
2555 //_ALLOC(the_pFile,sizeof(pFile));
2556 the_pFile = Safe_calloc(1,sizeof(pFile));
2557 the_pFile->pbHead = the_pFile->pbTail = pb;
2558 the_pFile->functions = NULL;
2562 the_pFile->pbTail->next = pb;
2563 pb->prev = the_pFile->pbTail;
2565 the_pFile->pbTail = pb;
2568 /*-----------------------------------------------------------------*/
2569 /* removepBlock - remove a pBlock from the pFile */
2570 /*-----------------------------------------------------------------*/
2571 void removepBlock(pBlock *pb)
2579 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2581 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2584 if(pbs == the_pFile->pbHead)
2585 the_pFile->pbHead = pbs->next;
2587 if (pbs == the_pFile->pbTail)
2588 the_pFile->pbTail = pbs->prev;
2591 pbs->next->prev = pbs->prev;
2594 pbs->prev->next = pbs->next;
2601 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2605 /*-----------------------------------------------------------------*/
2606 /* printpCode - write the contents of a pCode to a file */
2607 /*-----------------------------------------------------------------*/
2608 void printpCode(FILE *of, pCode *pc)
2619 fprintf(of,"warning - unable to print pCode\n");
2622 /*-----------------------------------------------------------------*/
2623 /* printpBlock - write the contents of a pBlock to a file */
2624 /*-----------------------------------------------------------------*/
2625 void printpBlock(FILE *of, pBlock *pb)
2635 for(pc = pb->pcHead; pc; pc = pc->next) {
2640 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2650 /*-----------------------------------------------------------------*/
2652 /* pCode processing */
2656 /*-----------------------------------------------------------------*/
2658 void unlinkpCode(pCode *pc)
2664 fprintf(stderr,"Unlinking: ");
2665 printpCode(stderr, pc);
2668 pc->prev->next = pc->next;
2670 pc->next->prev = pc->prev;
2673 /* RN: I believe this should be right here, but this did not
2674 * cure the bug I was hunting... */
2675 /* must keep labels -- attach to following instruction */
2676 if (isPCI(pc) && PCI(pc)->label && pc->next)
2678 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2681 pBranchAppend (pcnext->label, PCI(pc)->label);
2685 pc->prev = pc->next = NULL;
2689 /*-----------------------------------------------------------------*/
2690 /*-----------------------------------------------------------------*/
2692 static void genericDestruct(pCode *pc)
2698 /* For instructions, tell the register (if there's one used)
2699 * that it's no longer needed */
2700 regs *reg = getRegFromInstruction(pc);
2702 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2705 /* Instead of deleting the memory used by this pCode, mark
2706 * the object as bad so that if there's a pointer to this pCode
2707 * dangling around somewhere then (hopefully) when the type is
2708 * checked we'll catch it.
2713 addpCode2pBlock(pb_dead_pcodes, pc);
2720 /*-----------------------------------------------------------------*/
2721 /* Copies the pCodeInstruction flow pointer from source pCode */
2722 /*-----------------------------------------------------------------*/
2723 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2725 pCodeFlow *pcflow = 0;
2726 for (p=pcs; p; p=p->prev) {
2728 pcflow = PCI(p)->pcflow;
2732 pcflow = (pCodeFlow*)p;
2736 PCI(pcd)->pcflow = pcflow;
2739 /*-----------------------------------------------------------------*/
2740 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2741 /* into the pCode chain containing pc1 */
2742 /*-----------------------------------------------------------------*/
2743 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2749 pc2->next = pc1->next;
2751 pc1->next->prev = pc2;
2757 /* If this is an instrution type propogate the flow */
2759 CopyFlow(PCI(pc2),pc1);
2762 /*------------------------------------------------------------------*/
2763 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2764 /* into the pCode chain containing pc1 */
2765 /*------------------------------------------------------------------*/
2766 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2772 pc2->prev = pc1->prev;
2774 pc1->prev->next = pc2;
2780 /* If this is an instrution type propogate the flow */
2782 CopyFlow(PCI(pc2),pc1);
2785 /*-----------------------------------------------------------------*/
2786 /* pCodeOpCopy - copy a pcode operator */
2787 /*-----------------------------------------------------------------*/
2788 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2790 pCodeOp *pcopnew=NULL;
2795 switch(pcop->type) {
2798 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2799 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2807 case PO_GPR_REGISTER:
2809 case PO_GPR_POINTER:
2810 case PO_SFR_REGISTER:
2814 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2815 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2816 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2817 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2821 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2822 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2823 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2827 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2828 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2834 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2835 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2836 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2840 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2841 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2842 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2846 /* Here we expand the wild card into the appropriate type: */
2847 /* By recursively calling pCodeOpCopy */
2848 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2849 if(PCOW(pcop)->matched)
2850 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2853 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2854 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2855 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2862 assert ( !"unhandled pCodeOp type copied" );
2867 pcopnew->name = Safe_strdup(pcop->name);
2869 pcopnew->name = NULL;
2874 /*-----------------------------------------------------------------*/
2875 /* popCopyReg - copy a pcode operator */
2876 /*-----------------------------------------------------------------*/
2877 pCodeOp *popCopyReg(pCodeOpReg *pc)
2881 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2882 pcor->pcop.type = pc->pcop.type;
2884 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2885 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2887 pcor->pcop.name = NULL;
2889 if (pcor->pcop.type == PO_IMMEDIATE){
2890 PCOL(pcor)->lit = PCOL(pc)->lit;
2893 pcor->rIdx = pc->rIdx;
2897 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2902 /*-----------------------------------------------------------------*/
2903 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2904 /*-----------------------------------------------------------------*/
2905 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2907 pCodeInstruction *new_pci;
2910 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2912 new_pci = PCI(newpCode(pci->op,pci->pcop));
2914 new_pci->pc.pb = pci->pc.pb;
2915 new_pci->from = pci->from;
2916 new_pci->to = pci->to;
2917 new_pci->label = pci->label;
2918 new_pci->pcflow = pci->pcflow;
2920 return PCODE(new_pci);
2923 /*-----------------------------------------------------------------*/
2924 /*-----------------------------------------------------------------*/
2925 void pCodeDeleteChain(pCode *f,pCode *t)
2930 DFPRINTF((stderr,"delete pCode:\n"));
2932 //f->print(stderr,f);
2933 //f->delete(f); this dumps core...
2938 /*-----------------------------------------------------------------*/
2939 /*-----------------------------------------------------------------*/
2940 void pBlockRegs(FILE *of, pBlock *pb)
2945 r = setFirstItem(pb->tregisters);
2947 r = setNextItem(pb->tregisters);
2952 /*-----------------------------------------------------------------*/
2953 /*-----------------------------------------------------------------*/
2954 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2959 int use_buffer = 1; // copy the string to the passed buffer pointer
2964 use_buffer = 0; // Don't bother copying the string to the buffer.
2968 switch(pcop->type) {
2972 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2975 //return PCOR(pcop)->r->name;
2979 if (PCOR(pcop)->r->type == REG_STK)
2980 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2982 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2985 SAFE_snprintf(&buffer,&size,"%s",r->name);
2994 if(PCOI(pcop)->_const) {
2996 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
2997 switch(PCOI(pcop)->offset) {
2999 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3002 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3005 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3006 assert ( !"offset too large" );
3007 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3010 8 * PCOI(pcop)->offset );
3013 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3015 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3016 SAFE_snprintf(&s,&size,"(%s + %d)",
3020 switch(PCOI(pcop)->offset) {
3022 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3025 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3028 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3029 assert ( !"offset too large" );
3030 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3040 //size = sizeof(buffer);
3041 if( PCOR(pcop)->instance) {
3042 SAFE_snprintf(&s,&size,"(%s + %d)",
3044 PCOR(pcop)->instance );
3045 //fprintf(stderr,"PO_DIR %s\n",buffer);
3047 SAFE_snprintf(&s,&size,"%s",pcop->name);
3053 if(PCOLAB(pcop)->offset == 1)
3054 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3056 SAFE_snprintf(&s,&size,"%s",pcop->name);
3063 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3066 return PCOR(pcop)->r->name;
3069 /* fall through to the default case */
3073 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3081 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3082 __FILE__, __LINE__, __FUNCTION__,
3085 return "NO operand";
3089 /*-----------------------------------------------------------------*/
3090 /*-----------------------------------------------------------------*/
3091 static char *get_op_from_instruction( pCodeInstruction *pcc)
3095 return get_op(pcc->pcop,NULL,0);
3097 return ("ERROR Null: get_op_from_instruction");
3101 /*-----------------------------------------------------------------*/
3102 /*-----------------------------------------------------------------*/
3103 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3105 fprintf(of,"pcodeopprint- not implemented\n");
3108 /*-----------------------------------------------------------------*/
3109 /* pCode2str - convert a pCode instruction to string */
3110 /*-----------------------------------------------------------------*/
3111 char *pCode2str(char *str, size_t size, pCode *pc)
3119 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3121 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3123 if(PCI(pc)->isBitInst) {
3124 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3125 char *name = PCI(pc)->pcop->name;
3127 name = PCOR(PCI(pc)->pcop)->r->name;
3128 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3129 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3131 SAFE_snprintf(&s,&size,"%s,%d", name,
3132 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3133 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3134 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3136 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3137 //PCI(pc)->pcop->t.bit );
3139 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3140 if( PCI(pc)->num_ops == 2)
3141 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3143 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3145 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3146 if( PCI(pc)->num_ops == 2)
3147 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3154 /* assuming that comment ends with a \n */
3155 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3159 /* assuming that inline code ends with a \n */
3160 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3164 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3167 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3170 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3173 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3176 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3177 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);
3180 if(PCAD(pc)->directive) {
3181 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3182 } else if(PCAD(pc)->arg) {
3183 /* special case to handle inline labels without a tab */
3184 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3189 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3195 /*-----------------------------------------------------------------*/
3196 /* genericPrint - the contents of a pCode to a file */
3197 /*-----------------------------------------------------------------*/
3198 static void genericPrint(FILE *of, pCode *pc)
3205 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3209 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3213 // If the opcode has a label, print that first
3216 pCodeInstruction *pci = PCI(pc);
3217 pBranch *pbl = pci->label;
3218 while(pbl && pbl->pc) {
3219 if(pbl->pc->type == PC_LABEL)
3220 pCodePrintLabel(of, pbl->pc);
3225 genericPrint(of,PCODE(pci->cline));
3228 pCode2str(str, 256, pc);
3230 fprintf(of,"%s",str);
3234 pCodeOpReg *pcor = PCOR(pci->pcop);
3235 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3237 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3238 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3239 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3244 pBranch *dpb = pc->to; // debug
3246 switch ( dpb->pc->type) {
3248 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3251 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3254 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3257 fprintf(of, "\t;flow");
3271 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3272 if(PCW(pc)->pci.label)
3273 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3275 if(PCW(pc)->operand) {
3276 fprintf(of,";\toperand ");
3277 pCodeOpPrint(of,PCW(pc)->operand );
3283 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3284 if(PCFL(pc)->ancestor)
3285 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3287 fprintf(of,"; from: ");
3289 pCodeFlowLink *link;
3290 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3292 fprintf(of,"%03x ",link->pcflow->pc.seq);
3295 fprintf(of,"; to: ");
3297 pCodeFlowLink *link;
3298 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3300 fprintf(of,"%03x ",link->pcflow->pc.seq);
3308 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3309 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3314 pBranch *pbl = PCAD(pc)->pci.label;
3315 while(pbl && pbl->pc) {
3316 if(pbl->pc->type == PC_LABEL)
3317 pCodePrintLabel(of, pbl->pc);
3321 if(PCAD(pc)->directive) {
3322 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3325 /* special case to handle inline labels without tab */
3326 fprintf(of, "%s\n", PCAD(pc)->arg);
3332 fprintf(of,"unknown pCode type %d\n",pc->type);
3336 /*-----------------------------------------------------------------*/
3337 /* pCodePrintFunction - prints function begin/end */
3338 /*-----------------------------------------------------------------*/
3340 static void pCodePrintFunction(FILE *of, pCode *pc)
3346 if( ((pCodeFunction *)pc)->modname)
3347 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3349 if(PCF(pc)->fname) {
3350 pBranch *exits = PCF(pc)->to;
3352 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3355 exits = exits->next;
3358 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3361 if((PCF(pc)->from &&
3362 PCF(pc)->from->pc->type == PC_FUNCTION &&
3363 PCF(PCF(pc)->from->pc)->fname) )
3364 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3366 fprintf(of,"; exit point [can't find entry point]\n");
3369 /*-----------------------------------------------------------------*/
3370 /* pCodePrintLabel - prints label */
3371 /*-----------------------------------------------------------------*/
3373 static void pCodePrintLabel(FILE *of, pCode *pc)
3380 fprintf(of,"%s\n",PCL(pc)->label);
3381 else if (PCL(pc)->key >=0)
3382 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3384 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3388 /*-----------------------------------------------------------------*/
3389 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3390 /* remove it if it is found. */
3391 /*-----------------------------------------------------------------*/
3392 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3398 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3399 b = PCI(pcl)->label;
3401 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3405 //fprintf (stderr, "%s \n",__FUNCTION__);
3406 //pcl->print(stderr,pcl);
3407 //pc->print(stderr,pc);
3410 //fprintf (stderr, "found label\n");
3414 bprev->next = b->next; /* Not first pCode in chain */
3418 PCI(pcl)->label = b->next; /* First pCode in chain */
3421 return; /* A label can't occur more than once */
3428 /*-----------------------------------------------------------------*/
3429 /*-----------------------------------------------------------------*/
3430 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3449 /*-----------------------------------------------------------------*/
3450 /* pBranchLink - given two pcodes, this function will link them */
3451 /* together through their pBranches */
3452 /*-----------------------------------------------------------------*/
3453 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3457 // Declare a new branch object for the 'from' pCode.
3459 //_ALLOC(b,sizeof(pBranch));
3460 b = Safe_calloc(1,sizeof(pBranch));
3461 b->pc = PCODE(t); // The link to the 'to' pCode.
3464 f->to = pBranchAppend(f->to,b);
3466 // Now do the same for the 'to' pCode.
3468 //_ALLOC(b,sizeof(pBranch));
3469 b = Safe_calloc(1,sizeof(pBranch));
3473 t->from = pBranchAppend(t->from,b);
3478 /*-----------------------------------------------------------------*/
3479 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3481 /*-----------------------------------------------------------------*/
3482 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3495 /*-----------------------------------------------------------------*/
3496 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3497 /*-----------------------------------------------------------------*/
3498 static void pCodeUnlink(pCode *pc)
3503 if(!pc->prev || !pc->next) {
3504 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3508 /* first remove the pCode from the chain */
3509 pc->prev->next = pc->next;
3510 pc->next->prev = pc->prev;
3512 /* Now for the hard part... */
3514 /* Remove the branches */
3518 pc1 = pb1->pc; /* Get the pCode that branches to the
3519 * one we're unlinking */
3521 /* search for the link back to this pCode (the one we're
3523 if(pb2 = pBranchFind(pc1->to,pc)) {
3524 pb2->pc = pc->to->pc; // make the replacement
3526 /* if the pCode we're unlinking contains multiple 'to'
3527 * branches (e.g. this a skip instruction) then we need
3528 * to copy these extra branches to the chain. */
3530 pBranchAppend(pb2, pc->to->next);
3539 /*-----------------------------------------------------------------*/
3540 /*-----------------------------------------------------------------*/
3542 static void genericAnalyze(pCode *pc)
3552 // Go through the pCodes that are in pCode chain and link
3553 // them together through the pBranches. Note, the pCodes
3554 // are linked together as a contiguous stream like the
3555 // assembly source code lines. The linking here mimics this
3556 // except that comments are not linked in.
3558 pCode *npc = pc->next;
3560 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3561 pBranchLink(pc,npc);
3566 /* reached the end of the pcode chain without finding
3567 * an instruction we could link to. */
3571 fprintf(stderr,"analyze PC_FLOW\n");
3575 fprintf(stderr,";A bad pCode is being used\n");
3581 /*-----------------------------------------------------------------*/
3582 /*-----------------------------------------------------------------*/
3583 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3587 if(pc->type == PC_LABEL) {
3588 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3591 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3592 pbr = PCI(pc)->label;
3594 if(pbr->pc->type == PC_LABEL) {
3595 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3605 /*-----------------------------------------------------------------*/
3606 /*-----------------------------------------------------------------*/
3607 int checkLabel(pCode *pc)
3611 if(pc && isPCI(pc)) {
3612 pbr = PCI(pc)->label;
3614 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3624 /*-----------------------------------------------------------------*/
3625 /* findLabelinpBlock - Search the pCode for a particular label */
3626 /*-----------------------------------------------------------------*/
3627 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3634 for(pc = pb->pcHead; pc; pc = pc->next)
3635 if(compareLabel(pc,pcop_label))
3641 /*-----------------------------------------------------------------*/
3642 /* findLabel - Search the pCode for a particular label */
3643 /*-----------------------------------------------------------------*/
3644 pCode * findLabel(pCodeOpLabel *pcop_label)
3652 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3653 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3657 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3661 /*-----------------------------------------------------------------*/
3662 /* findNextpCode - given a pCode, find the next of type 'pct' */
3663 /* in the linked list */
3664 /*-----------------------------------------------------------------*/
3665 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3678 /*-----------------------------------------------------------------*/
3679 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3680 /* in the linked list */
3681 /*-----------------------------------------------------------------*/
3682 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3686 if(pc->type == pct) {
3688 static unsigned int stop;
3690 stop++; // Place break point here
3701 /*-----------------------------------------------------------------*/
3702 /* findNextInstruction - given a pCode, find the next instruction */
3703 /* in the linked list */
3704 /*-----------------------------------------------------------------*/
3705 pCode * findNextInstruction(pCode *pci)
3710 if((pc->type == PC_OPCODE)
3711 || (pc->type == PC_WILD)
3712 || (pc->type == PC_ASMDIR))
3716 fprintf(stderr,"findNextInstruction: ");
3717 printpCode(stderr, pc);
3722 //fprintf(stderr,"Couldn't find instruction\n");
3726 /*-----------------------------------------------------------------*/
3727 /* findNextInstruction - given a pCode, find the next instruction */
3728 /* in the linked list */
3729 /*-----------------------------------------------------------------*/
3730 pCode * findPrevInstruction(pCode *pci)
3736 if((pc->type == PC_OPCODE)
3737 || (pc->type == PC_WILD)
3738 || (pc->type == PC_ASMDIR))
3743 fprintf(stderr,"pic16_findPrevInstruction: ");
3744 printpCode(stderr, pc);
3749 //fprintf(stderr,"Couldn't find instruction\n");
3753 /*-----------------------------------------------------------------*/
3754 /* findFunctionEnd - given a pCode find the end of the function */
3755 /* that contains it */
3756 /*-----------------------------------------------------------------*/
3757 pCode * findFunctionEnd(pCode *pc)
3760 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3766 fprintf(stderr,"Couldn't find function end\n");
3771 /*-----------------------------------------------------------------*/
3772 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3773 /* instruction with which it is associated. */
3774 /*-----------------------------------------------------------------*/
3775 static void AnalyzeLabel(pCode *pc)
3784 static void AnalyzeGOTO(pCode *pc)
3787 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3791 static void AnalyzeSKIP(pCode *pc)
3794 pBranchLink(pc,findNextInstruction(pc->next));
3795 pBranchLink(pc,findNextInstruction(pc->next->next));
3799 static void AnalyzeRETURN(pCode *pc)
3802 // branch_link(pc,findFunctionEnd(pc->next));
3808 /*-----------------------------------------------------------------*/
3809 /*-----------------------------------------------------------------*/
3810 regs * getRegFromInstruction(pCode *pc)
3816 PCI(pc)->num_ops == 0 )
3819 switch(PCI(pc)->pcop->type) {
3826 case PO_SFR_REGISTER:
3829 return PCOR(PCI(pc)->pcop)->r;
3831 case PO_GPR_REGISTER:
3834 r = PCOR(PCI(pc)->pcop)->r;
3837 return dirregWithName(PCI(pc)->pcop->name);
3843 r = PCOI(PCI(pc)->pcop)->r;
3846 return dirregWithName(PCI(pc)->pcop->name);
3856 /*-----------------------------------------------------------------*/
3857 /*-----------------------------------------------------------------*/
3859 void AnalyzepBlock(pBlock *pb)
3866 /* Find all of the registers used in this pBlock
3867 * by looking at each instruction and examining it's
3870 for(pc = pb->pcHead; pc; pc = pc->next) {
3872 /* Is this an instruction with operands? */
3873 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3875 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3876 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3878 /* Loop through all of the registers declared so far in
3879 this block and see if we find this one there */
3881 regs *r = setFirstItem(pb->tregisters);
3884 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3885 PCOR(PCI(pc)->pcop)->r = r;
3888 r = setNextItem(pb->tregisters);
3892 /* register wasn't found */
3893 //r = Safe_calloc(1, sizeof(regs));
3894 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3895 //addSet(&pb->tregisters, r);
3896 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3897 //PCOR(PCI(pc)->pcop)->r = r;
3898 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3900 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3903 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3904 if(PCOR(PCI(pc)->pcop)->r) {
3905 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3906 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3908 if(PCI(pc)->pcop->name)
3909 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3911 fprintf(stderr,"ERROR: NULL register\n");
3920 /*-----------------------------------------------------------------*/
3922 /*-----------------------------------------------------------------*/
3923 void InsertpFlow(pCode *pc, pCode **pflow)
3926 PCFL(*pflow)->end = pc;
3928 if(!pc || !pc->next)
3931 *pflow = newpCodeFlow();
3932 pCodeInsertAfter(pc, *pflow);
3935 /*-----------------------------------------------------------------*/
3936 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3937 /* the flow blocks. */
3939 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3940 * point the instruction flow changes.
3942 /*-----------------------------------------------------------------*/
3943 void BuildFlow(pBlock *pb)
3946 pCode *last_pci=NULL;
3953 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3954 /* Insert a pCodeFlow object at the beginning of a pBlock */
3956 InsertpFlow(pb->pcHead, &pflow);
3958 //pflow = newpCodeFlow(); /* Create a new Flow object */
3959 //pflow->next = pb->pcHead; /* Make the current head the next object */
3960 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3961 //pb->pcHead = pflow; /* Make the Flow object the head */
3964 for( pc = findNextInstruction(pb->pcHead);
3966 pc=findNextInstruction(pc)) {
3969 PCI(pc)->pcflow = PCFL(pflow);
3971 //fprintf(stderr," build: ");
3972 //pc->print(stderr, pc);
3973 //pflow->print(stderr,pflow);
3975 if (checkLabel(pc)) {
3977 /* This instruction marks the beginning of a
3978 * new flow segment */
3983 /* If the previous pCode is not a flow object, then
3984 * insert a new flow object. (This check prevents
3985 * two consecutive flow objects from being insert in
3986 * the case where a skip instruction preceeds an
3987 * instruction containing a label.) */
3989 last_pci = findPrevInstruction (pc->prev);
3991 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3992 InsertpFlow(last_pci, &pflow);
3994 PCI(pc)->pcflow = PCFL(pflow);
3998 if(isPCI_SKIP(pc)) {
4000 /* The two instructions immediately following this one
4001 * mark the beginning of a new flow segment */
4003 while(pc && isPCI_SKIP(pc)) {
4005 PCI(pc)->pcflow = PCFL(pflow);
4009 InsertpFlow(pc, &pflow);
4010 pc=findNextInstruction(pc->next);
4018 PCI(pc)->pcflow = PCFL(pflow);
4020 InsertpFlow(pc, &pflow);
4022 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4024 InsertpFlow(pc, &pflow);
4033 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4035 PCFL(pflow)->end = pb->pcTail;
4038 /*-------------------------------------------------------------------*/
4039 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4040 /* the flow blocks. */
4042 * unBuildFlow removes pCodeFlow objects from a pCode chain
4044 /*-----------------------------------------------------------------*/
4045 void unBuildFlow(pBlock *pb)
4060 if(PCI(pc)->pcflow) {
4061 //free(PCI(pc)->pcflow);
4062 PCI(pc)->pcflow = NULL;
4065 } else if(isPCFL(pc) )
4074 /*-----------------------------------------------------------------*/
4075 /*-----------------------------------------------------------------*/
4076 void dumpCond(int cond)
4079 static char *pcc_str[] = {
4093 int ncond = sizeof(pcc_str) / sizeof(char *);
4096 fprintf(stderr, "0x%04X\n",cond);
4098 for(i=0,j=1; i<ncond; i++, j<<=1)
4100 fprintf(stderr, " %s\n",pcc_str[i]);
4104 /*-----------------------------------------------------------------*/
4105 /*-----------------------------------------------------------------*/
4106 void FlowStats(pCodeFlow *pcflow)
4114 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4116 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4119 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4124 fprintf(stderr, " FlowStats inCond: ");
4125 dumpCond(pcflow->inCond);
4126 fprintf(stderr, " FlowStats outCond: ");
4127 dumpCond(pcflow->outCond);
4131 /*-----------------------------------------------------------------*
4132 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4133 * if it affects the banking bits.
4135 * return: -1 == Banking bits are unaffected by this pCode.
4137 * return: > 0 == Banking bits are affected.
4139 * If the banking bits are affected, then the returned value describes
4140 * which bits are affected and how they're affected. The lower half
4141 * of the integer maps to the bits that are affected, the upper half
4142 * to whether they're set or cleared.
4144 *-----------------------------------------------------------------*/
4146 #define SET_BANK_BIT (1 << 16)
4147 #define CLR_BANK_BIT 0
4149 static int isBankInstruction(pCode *pc)
4157 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4159 // Check to see if the register banks are changing
4160 if(PCI(pc)->isModReg) {
4162 pCodeOp *pcop = PCI(pc)->pcop;
4163 switch(PCI(pc)->op) {
4166 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4167 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4168 return SET_BANK_BIT | PIC_RP0_BIT;
4171 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4172 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4173 return CLR_BANK_BIT | PIC_RP0_BIT;
4178 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4179 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4180 return CLR_BANK_BIT | PIC_RP1_BIT;
4182 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4183 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4184 return CLR_BANK_BIT | PIC_RP1_BIT;
4188 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4189 //genericPrint(stderr, pc);
4200 /*-----------------------------------------------------------------*/
4201 /*-----------------------------------------------------------------*/
4203 static void FillFlow(pCodeFlow *pcflow)
4211 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4213 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4216 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4223 isBankInstruction(pc);
4225 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4228 fprintf(stderr, " FillFlow - Bad end of flow\n");
4230 fprintf(stderr, " FillFlow - Ending flow with\n ");
4231 pc->print(stderr,pc);
4234 fprintf(stderr, " FillFlow inCond: ");
4235 dumpCond(pcflow->inCond);
4236 fprintf(stderr, " FillFlow outCond: ");
4237 dumpCond(pcflow->outCond);
4242 /*-----------------------------------------------------------------*/
4243 /*-----------------------------------------------------------------*/
4244 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4246 pCodeFlowLink *fromLink, *toLink;
4248 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4249 if (from) from->pc.print(stderr, &from->pc);
4250 else fprintf(stderr, "(null)");
4251 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4252 from && from->pcflow ? from->pcflow->pc.seq : 0,
4253 to && to->pcflow ? to->pcflow->pc.seq : 0);
4254 if (to) to->pc.print(stderr, &to->pc);
4255 else fprintf(stderr, "(null)");
4258 if(!from || !to || !to->pcflow || !from->pcflow)
4261 fromLink = newpCodeFlowLink(from->pcflow);
4262 toLink = newpCodeFlowLink(to->pcflow);
4264 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4265 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4269 /*-----------------------------------------------------------------*
4270 * void LinkFlow(pBlock *pb)
4272 * In BuildFlow, the PIC code has been partitioned into contiguous
4273 * non-branching segments. In LinkFlow, we determine the execution
4274 * order of these segments. For example, if one of the segments ends
4275 * with a skip, then we know that there are two possible flow segments
4276 * to which control may be passed.
4277 *-----------------------------------------------------------------*/
4278 void LinkFlow(pBlock *pb)
4284 //fprintf(stderr,"linkflow \n");
4286 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4288 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4291 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4293 //fprintf(stderr," link: ");
4294 //pcflow->print(stderr,pcflow);
4296 //FillFlow(PCFL(pcflow));
4298 /* find last instruction in flow */
4299 pc = findPrevInstruction (PCFL(pcflow)->end);
4301 fprintf(stderr, "%s: flow without end (%u)?\n",
4302 __FUNCTION__, pcflow->seq );
4306 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4307 //pc->print(stderr, pc);
4308 if(isPCI_SKIP(pc)) {
4309 //fprintf(stderr, "ends with skip\n");
4310 //pc->print(stderr,pc);
4311 pct=findNextInstruction(pc->next);
4312 LinkFlow_pCode(PCI(pc),PCI(pct));
4313 pct=findNextInstruction(pct->next);
4314 LinkFlow_pCode(PCI(pc),PCI(pct));
4318 if(isPCI_BRANCH(pc)) {
4319 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4321 //fprintf(stderr, "ends with branch\n ");
4322 //pc->print(stderr,pc);
4324 if(!(pcol && isPCOLAB(pcol))) {
4325 if((PCI(pc)->op != POC_RETLW)
4326 && (PCI(pc)->op != POC_RETURN)
4327 && (PCI(pc)->op != POC_CALL)
4328 && (PCI(pc)->op != POC_RETFIE) )
4330 pc->print(stderr,pc);
4331 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4335 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4336 LinkFlow_pCode(PCI(pc),PCI(pct));
4338 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4339 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4340 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4342 /* link CALLs to next instruction */
4343 if (PCI(pc)->op != POC_CALL) continue;
4347 //fprintf(stderr, "ends with non-branching instruction:\n");
4348 //pc->print(stderr,pc);
4350 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4356 //fprintf(stderr, "ends with unknown\n");
4357 //pc->print(stderr,pc);
4361 fprintf(stderr, "ends with nothing: ERROR\n");
4365 /*-----------------------------------------------------------------*/
4366 /*-----------------------------------------------------------------*/
4368 /*-----------------------------------------------------------------*/
4369 /*-----------------------------------------------------------------*/
4370 int isPCinFlow(pCode *pc, pCode *pcflow)
4376 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4379 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4385 /*-----------------------------------------------------------------*/
4386 /*-----------------------------------------------------------------*/
4388 static void BanksUsedFlow2(pCode *pcflow)
4397 if(!isPCFL(pcflow)) {
4398 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4402 pc = findNextInstruction(pcflow->next);
4404 PCFL(pcflow)->lastBank = -1;
4406 while(isPCinFlow(pc,pcflow)) {
4408 int bank_selected = isBankInstruction(pc);
4410 //if(PCI(pc)->pcflow)
4411 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4413 if(bank_selected > 0) {
4414 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4416 // This instruction is modifying banking bits before accessing registers
4418 PCFL(pcflow)->firstBank = -1;
4420 if(PCFL(pcflow)->lastBank == -1)
4421 PCFL(pcflow)->lastBank = 0;
4423 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4424 if(bank_selected & SET_BANK_BIT)
4425 PCFL(pcflow)->lastBank |= bank;
4429 reg = getRegFromInstruction(pc);
4431 if(reg && !isREGinBank(reg, bank)) {
4432 int allbanks = REGallBanks(reg);
4434 PCFL(pcflow)->firstBank = allbanks;
4436 PCFL(pcflow)->lastBank = allbanks;
4443 pc = findNextInstruction(pc->next);
4446 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4447 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4450 /*-----------------------------------------------------------------*/
4451 /*-----------------------------------------------------------------*/
4453 static void BanksUsedFlow(pBlock *pb)
4458 //pb->pcHead->print(stderr, pb->pcHead);
4460 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4461 //pcflow->print(stderr,pcflow);
4463 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4465 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4467 BanksUsedFlow2(pcflow);
4473 void pCodeReplace (pCode *old, pCode *new)
4475 pCodeInsertAfter (old, new);
4477 /* special handling for pCodeInstructions */
4478 if (isPCI(new) && isPCI(old))
4480 assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4481 PCI(new)->from = PCI(old)->from;
4482 PCI(new)->to = PCI(old)->to;
4483 PCI(new)->label = PCI(old)->label;
4484 PCI(new)->pcflow = PCI(old)->pcflow;
4485 PCI(new)->cline = PCI(old)->cline;
4488 old->destruct (old);
4491 /*-----------------------------------------------------------------*/
4492 /* Inserts a new pCodeInstruction before an existing one */
4493 /*-----------------------------------------------------------------*/
4494 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4498 pcprev = findPrevInstruction(pci->pc.prev);
4500 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4502 /* Move the label, if there is one */
4505 new_pci->label = pci->label;
4509 /* Move the C code comment, if there is one */
4512 new_pci->cline = pci->cline;
4516 /* The new instruction has the same pcflow block */
4517 new_pci->pcflow = pci->pcflow;
4519 /* Arrrrg: is pci's previous instruction is a skip, we need to
4520 * change that into a jump (over pci and the new instruction) ... */
4521 if (pcprev && isPCI_SKIP(pcprev))
4523 symbol *lbl = newiTempLabel (NULL);
4524 pCode *label = newpCodeLabel (NULL, lbl->key);
4525 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4527 pCodeInsertAfter (pcprev, jump);
4529 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4531 pCodeInsertAfter((pCode*)pci, label);
4535 /*-----------------------------------------------------------------*/
4536 /*-----------------------------------------------------------------*/
4537 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4541 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4543 insertPCodeInstruction(pci, PCI(new_pc));
4546 /*-----------------------------------------------------------------*/
4547 /*-----------------------------------------------------------------*/
4548 static void insertBankSel(pCodeInstruction *pci, const char *name)
4552 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4553 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4554 if (pcop->name == 0)
4555 pcop->name = strdup(name);
4556 new_pc = newpCode(POC_BANKSEL, pcop);
4558 insertPCodeInstruction(pci, PCI(new_pc));
4561 /*-----------------------------------------------------------------*/
4562 /* If the register is a fixed known addess then we can assign the */
4563 /* bank selection bits. Otherwise the linker is going to assign */
4564 /* the register location and thus has to set bank selection bits */
4565 /* through the banksel directive. */
4566 /* One critical assumption here is that within this C module all */
4567 /* the locally allocated registers are in the same udata sector. */
4568 /* Therefore banksel is only called for external registers or the */
4569 /* first time a local register is encountered. */
4570 /*-----------------------------------------------------------------*/
4571 static int LastRegIdx = -1; /* If the previous register is the same one again then no need to change bank. */
4572 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4575 int a = reg->alias>>7;
4577 return cur_bank; // This register is available in all banks
4578 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4579 return cur_bank; // This register is available in banks 0 & 1
4581 if (reg->address&0x80) {
4582 if ((cur_bank==1)||(cur_bank==3)) {
4583 return cur_bank; // This register is available in banks 1 & 3
4586 if ((cur_bank==0)||(cur_bank==1)) {
4587 return cur_bank; // This register is available in banks 0 & 2
4593 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4595 LastRegIdx = reg->rIdx;
4599 bank = REG_BANK(reg);
4600 } else if (reg->isExtern) {
4601 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4603 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4605 if ((cur_bank == 'L')&&(bank == 'L')) { // If current bank and new bank are both allocated locally by the linker, then assume it is in same bank.
4606 return 'L'; // Local registers are presumed to be in same linker assigned bank
4607 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4608 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4609 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4610 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4611 } 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
4612 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4613 if (getMaxRam()&0x100)
4614 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4615 } else { // Current bank and new register banks known - can set bank bits
4616 switch((cur_bank^bank) & 3) {
4620 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4623 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4626 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4627 if (getMaxRam()&0x100)
4628 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4636 /*-----------------------------------------------------------------*/
4637 /* Check for bank selection pcodes instructions and modify */
4638 /* cur_bank to match. */
4639 /*-----------------------------------------------------------------*/
4640 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4642 if (isSTATUS_REG(reg)) {
4644 if (PCI(pc)->op == POC_BCF) {
4645 int old_bank = *cur_bank;
4646 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4647 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4648 if (*cur_bank & ~(0x3))
4651 *cur_bank = *cur_bank&0x2;
4652 LastRegIdx = reg->rIdx;
4653 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4654 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4655 if (*cur_bank & ~(0x3))
4658 *cur_bank = *cur_bank&0x1;
4659 LastRegIdx = reg->rIdx;
4661 return old_bank != *cur_bank;
4664 if (PCI(pc)->op == POC_BSF) {
4665 int old_bank = *cur_bank;
4666 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4667 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4668 if (*cur_bank & ~(0x3))
4671 *cur_bank = (*cur_bank&0x2) | 0x1;
4672 LastRegIdx = reg->rIdx;
4673 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4674 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4675 if (*cur_bank & ~(0x3))
4678 *cur_bank = (*cur_bank&0x1) | 0x2;
4679 LastRegIdx = reg->rIdx;
4681 return old_bank != *cur_bank;
4684 } else if (PCI(pc)->op == POC_BANKSEL) {
4685 int old_bank = *cur_bank;
4686 regs *r = PCOR(PCI(pc)->pcop)->r;
4687 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4688 LastRegIdx = reg->rIdx;
4689 return old_bank != *cur_bank;
4695 /*-----------------------------------------------------------------*/
4696 /* Set bank selection if necessary */
4697 /*-----------------------------------------------------------------*/
4698 static int DoBankSelect(pCode *pc, int cur_bank) {
4706 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4707 LastRegIdx = -1; /* do not know which register is touched in the called function... */
4708 if (pcf && isPCF(pcf)) {
4710 int rbank = 'U'; // Undetermined
4711 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4712 // Check all the returns to work out what bank is selected
4713 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4715 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4717 rbank = PCI(pcfr)->pcflow->lastBank;
4719 if (rbank != PCI(pcfr)->pcflow->lastBank)
4720 return -1; // Unknown bank - multiple returns with different banks
4725 return -1; // Unknown bank
4727 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4728 /* Extern functions may use registers in different bank - must call banksel */
4729 return -1; /* Unknown bank */
4735 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4736 return -1; /* New bank unknown - linkers choice. */
4739 reg = getRegFromInstruction(pc);
4741 if (IsBankChange(pc,reg,&cur_bank))
4743 if (!isPCI_LIT(pc)) {
4745 /* Examine the instruction before this one to make sure it is
4746 * not a skip type instruction */
4747 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4749 /* This approach does not honor the presence of labels at this instruction... */
4750 //if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4751 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4753 // cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4755 if (!PCI(pc)->pcflow)
4756 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4758 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4764 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4767 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4775 pc = findNextInstruction(pcfl->pc.next);
4777 while(isPCinFlow(pc,PCODE(pcfl))) {
4779 cur_bank = DoBankSelect(pc,cur_bank);
4781 pc = findNextInstruction(pc->next);
4785 if(pcprev && cur_bank) {
4786 // Set bank state to unknown at the end of each flow block
4792 /*-----------------------------------------------------------------*/
4793 /*int compareBankFlow - compare the banking requirements between */
4795 /*-----------------------------------------------------------------*/
4797 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4800 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4803 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4806 if(pcflow->firstBank == -1)
4810 if(pcflowLink->pcflow->firstBank == -1) {
4811 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4812 pcflowLink->pcflow->to :
4813 pcflowLink->pcflow->from);
4814 return compareBankFlow(pcflow, pctl, toORfrom);
4818 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4821 pcflowLink->bank_conflict++;
4822 pcflowLink->pcflow->FromConflicts++;
4823 pcflow->ToConflicts++;
4826 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4829 pcflowLink->bank_conflict++;
4830 pcflowLink->pcflow->ToConflicts++;
4831 pcflow->FromConflicts++;
4835 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4836 pcflowLink->pcflow->pc.seq,
4837 pcflowLink->pcflow->FromConflicts,
4838 pcflowLink->pcflow->ToConflicts);
4844 /*-----------------------------------------------------------------*/
4845 /*-----------------------------------------------------------------*/
4847 void FixBankFlow(pBlock *pb)
4851 pCodeFlowLink *pcfl;
4853 pCode *pcflow_max_To=NULL;
4854 pCode *pcflow_max_From=NULL;
4855 int max_ToConflicts=0;
4856 int max_FromConflicts=0;
4858 /fprintf(stderr,"Fix Bank flow \n");
4859 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4863 First loop through all of the flow objects in this pcode block
4864 and fix the ones that have banking conflicts between the
4868 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4870 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4872 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4874 if(!isPCFL(pcflow)) {
4875 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4879 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4880 PCFL(pcflow)->firstBank >= 0 &&
4881 PCFL(pcflow)->lastBank >= 0 ) {
4883 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4884 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4886 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4887 BanksUsedFlow2(pcflow);
4892 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4894 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4896 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4901 if(!isPCFL(pcflow)) {
4902 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4906 PCFL(pcflow)->FromConflicts = 0;
4907 PCFL(pcflow)->ToConflicts = 0;
4912 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4913 pcfl = setFirstItem(PCFL(pcflow)->from);
4916 pc = PCODE(pcfl->pcflow);
4919 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4920 pc->print(stderr,pc);
4923 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4926 pcfl=setNextItem(PCFL(pcflow)->from);
4929 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4930 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4932 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4933 BanksUsedFlow2(pcflow);
4935 continue; / * Don't need to check the flow from here - it's already been fixed * /
4942 pcfl = setFirstItem(PCFL(pcflow)->to);
4945 pc = PCODE(pcfl->pcflow);
4947 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4948 pc->print(stderr,pc);
4951 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4954 pcfl=setNextItem(PCFL(pcflow)->to);
4957 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4958 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4960 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4961 BanksUsedFlow2(pcflow);
4966 Loop through the flow objects again and find the ones with the
4970 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4972 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4974 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4975 pcflow_max_To = pcflow;
4977 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4978 pcflow_max_From = pcflow;
4982 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4983 PCFL(pcflow_max_To)->pc.seq,
4984 PCFL(pcflow_max_To)->ToConflicts);
4987 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4988 PCFL(pcflow_max_From)->pc.seq,
4989 PCFL(pcflow_max_From)->FromConflicts);
4994 /*-----------------------------------------------------------------*/
4995 /*-----------------------------------------------------------------*/
4996 void DumpFlow(pBlock *pb)
5000 pCodeFlowLink *pcfl;
5003 fprintf(stderr,"Dump flow \n");
5004 pb->pcHead->print(stderr, pb->pcHead);
5006 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5007 pcflow->print(stderr,pcflow);
5009 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5011 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
5013 if(!isPCFL(pcflow)) {
5014 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5017 fprintf(stderr,"dumping: ");
5018 pcflow->print(stderr,pcflow);
5019 FlowStats(PCFL(pcflow));
5021 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5023 pc = PCODE(pcfl->pcflow);
5025 fprintf(stderr, " from seq %d:\n",pc->seq);
5027 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5028 pc->print(stderr,pc);
5033 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5035 pc = PCODE(pcfl->pcflow);
5037 fprintf(stderr, " to seq %d:\n",pc->seq);
5039 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5040 pc->print(stderr,pc);
5049 /*-----------------------------------------------------------------*/
5050 /*-----------------------------------------------------------------*/
5051 int OptimizepBlock(pBlock *pb)
5056 if(!pb || options.nopeep)
5059 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5061 for(pc = pb->pcHead; pc; pc = pc->next)
5062 matches += pCodePeepMatchRule(pc);
5065 pc = findNextInstruction(pb->pcHead);
5073 if(pCodePeepMatchRule(pc)) {
5078 pc = findNextInstruction(pcprev->next);
5080 pc = findNextInstruction(pb->pcHead);
5082 pc = findNextInstruction(pc->next);
5086 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5091 /*-----------------------------------------------------------------*/
5092 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5093 /*-----------------------------------------------------------------*/
5094 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5098 for(pc = pcs; pc; pc = pc->next) {
5100 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5102 (PCI(pc)->pcop->type == PO_LABEL) &&
5103 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5110 /*-----------------------------------------------------------------*/
5111 /*-----------------------------------------------------------------*/
5112 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5119 (PCI(pc)->pcop->type == PO_LABEL)) {
5121 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5123 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5125 free(pcol->pcop.name);
5127 /* If the key is negative, then we (probably) have a label to
5128 * a function and the name is already defined */
5131 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5135 //sprintf(buffer,"_%05d_DS_",pcl->key);
5137 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5139 pcol->pcop.name = Safe_strdup(s);
5140 pcol->key = pcl->key;
5141 //pc->print(stderr,pc);
5148 /*-----------------------------------------------------------------*/
5149 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5150 /* pCode chain if they're not used. */
5151 /*-----------------------------------------------------------------*/
5152 void pBlockRemoveUnusedLabels(pBlock *pb)
5154 pCode *pc; pCodeLabel *pcl;
5159 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5161 pBranch *pbr = PCI(pc)->label;
5162 if(pbr && pbr->next) {
5163 pCode *pcd = pb->pcHead;
5165 //fprintf(stderr, "multiple labels\n");
5166 //pc->print(stderr,pc);
5171 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5172 //fprintf(stderr,"Used by:\n");
5173 //pcd->print(stderr,pcd);
5175 exchangeLabels(PCL(pbr->pc),pcd);
5184 for(pc = pb->pcHead; pc; pc = pc->next) {
5186 if(isPCL(pc)) // Label pcode
5188 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5189 pcl = PCL(PCI(pc)->label->pc);
5192 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5194 /* This pCode is a label, so search the pBlock to see if anyone
5197 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5198 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5199 /* Couldn't find an instruction that refers to this label
5200 * So, unlink the pCode label from it's pCode chain
5201 * and destroy the label */
5202 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5204 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5205 if(pc->type == PC_LABEL) {
5207 pCodeLabelDestruct(pc);
5209 unlinkpCodeFromBranch(pc, PCODE(pcl));
5210 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5221 /*-----------------------------------------------------------------*/
5222 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5223 /* chain and put them into pBranches that are */
5224 /* associated with the appropriate pCode */
5226 /*-----------------------------------------------------------------*/
5227 void pBlockMergeLabels(pBlock *pb)
5230 pCode *pc, *pcnext=NULL;
5235 /* First, Try to remove any unused labels */
5236 //pBlockRemoveUnusedLabels(pb);
5238 /* Now loop through the pBlock and merge the labels with the opcodes */
5241 // for(pc = pb->pcHead; pc; pc = pc->next) {
5244 pCode *pcn = pc->next;
5246 if(pc->type == PC_LABEL) {
5248 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5249 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5250 if((pcnext = findNextInstruction(pc) )) {
5252 // Unlink the pCode label from it's pCode chain
5255 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5256 // And link it into the instruction's pBranch labels. (Note, since
5257 // it's possible to have multiple labels associated with one instruction
5258 // we must provide a means to accomodate the additional labels. Thus
5259 // the labels are placed into the singly-linked list "label" as
5260 // opposed to being a single member of the pCodeInstruction.)
5262 //_ALLOC(pbr,sizeof(pBranch));
5263 pbr = Safe_calloc(1,sizeof(pBranch));
5267 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5270 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5272 } else if(pc->type == PC_CSOURCE) {
5274 /* merge the source line symbolic info into the next instruction */
5275 if((pcnext = findNextInstruction(pc) )) {
5277 // Unlink the pCode label from it's pCode chain
5279 PCI(pcnext)->cline = PCCS(pc);
5280 //fprintf(stderr, "merging CSRC\n");
5281 //genericPrint(stderr,pcnext);
5287 pBlockRemoveUnusedLabels(pb);
5291 /*-----------------------------------------------------------------*/
5292 /*-----------------------------------------------------------------*/
5293 int OptimizepCode(char dbName)
5295 #define MAX_PASSES 4
5304 DFPRINTF((stderr," Optimizing pCode\n"));
5308 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5309 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5310 matches += OptimizepBlock(pb);
5313 while(matches && ++passes < MAX_PASSES);
5318 /*-----------------------------------------------------------------*/
5319 /* popCopyGPR2Bit - copy a pcode operator */
5320 /*-----------------------------------------------------------------*/
5322 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5326 pcop = newpCodeOpBit(pc->name, bitval, 0);
5328 if( !( (pcop->type == PO_LABEL) ||
5329 (pcop->type == PO_LITERAL) ||
5330 (pcop->type == PO_STR) ))
5331 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5337 /*-----------------------------------------------------------------*/
5338 /*-----------------------------------------------------------------*/
5339 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5342 int firstBank = 'U';
5347 for (pc=pb->pcHead; pc; pc=pc->next) {
5349 firstBank = PCFL(pc)->firstBank;
5353 if (firstBank != 'U') {
5354 /* This block has already been done */
5355 if (firstBank != cur_bank) {
5356 /* This block has started with a different bank - must adjust it */
5357 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5360 regs *reg = getRegFromInstruction(pc);
5362 DoBankSelect(pc,cur_bank);
5372 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5375 for (pc=pb->pcHead; pc; pc=pc->next) {
5377 PCFL(pc)->firstBank = cur_bank;
5380 cur_bank = DoBankSelect(pc,cur_bank);
5383 /* Trace through branches and set the bank selection as required. */
5386 for (pc=pb->pcHead; pc; pc=pc->next) {
5388 PCFL(pc)->firstBank = cur_bank;
5392 if (PCI(pc)->op == POC_GOTO) {
5393 int lastRegIdx = LastRegIdx;
5395 /* Trace through branch */
5396 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5399 regs *reg = getRegFromInstruction(pcl);
5401 int bankUnknown = -1;
5402 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5404 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5410 LastRegIdx = lastRegIdx;
5412 /* Keep track out current bank */
5413 regs *reg = getRegFromInstruction(pc);
5415 IsBankChange(pc,reg,&cur_bank);
5422 /*-----------------------------------------------------------------*/
5423 /*-----------------------------------------------------------------*/
5424 void pBlockDestruct(pBlock *pb)
5435 /*-----------------------------------------------------------------*/
5436 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5437 /* name dbName and combine them */
5438 /* into one block */
5439 /*-----------------------------------------------------------------*/
5440 void mergepBlocks(char dbName)
5443 pBlock *pb, *pbmerged = NULL,*pbn;
5445 pb = the_pFile->pbHead;
5447 //fprintf(stderr," merging blocks named %c\n",dbName);
5451 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5452 if( getpBlock_dbName(pb) == dbName) {
5454 //fprintf(stderr," merged block %c\n",dbName);
5459 addpCode2pBlock(pbmerged, pb->pcHead);
5460 /* addpCode2pBlock doesn't handle the tail: */
5461 pbmerged->pcTail = pb->pcTail;
5463 pb->prev->next = pbn;
5465 pbn->prev = pb->prev;
5470 //printpBlock(stderr, pbmerged);
5477 /*-----------------------------------------------------------------*/
5478 /* AnalyzeFlow - Examine the flow of the code and optimize */
5480 /* level 0 == minimal optimization */
5481 /* optimize registers that are used only by two instructions */
5482 /* level 1 == maximal optimization */
5483 /* optimize by looking at pairs of instructions that use the */
5485 /*-----------------------------------------------------------------*/
5487 void AnalyzeFlow(int level)
5489 static int times_called=0;
5497 /* if this is not the first time this function has been called,
5498 then clean up old flow information */
5499 if(times_called++) {
5500 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5503 RegsUnMapLiveRanges();
5509 /* Phase 2 - Flow Analysis - Register Banking
5511 * In this phase, the individual flow blocks are examined
5512 * and register banking is fixed.
5515 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5516 //FixRegisterBanking(pb);
5518 /* Phase 2 - Flow Analysis
5520 * In this phase, the pCode is partition into pCodeFlow
5521 * blocks. The flow blocks mark the points where a continuous
5522 * stream of instructions changes flow (e.g. because of
5523 * a call or goto or whatever).
5526 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5530 /* Phase 2 - Flow Analysis - linking flow blocks
5532 * In this phase, the individual flow blocks are examined
5533 * to determine their order of excution.
5536 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5539 /* Phase 3 - Flow Analysis - Flow Tree
5541 * In this phase, the individual flow blocks are examined
5542 * to determine their order of excution.
5545 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5549 /* Phase x - Flow Analysis - Used Banks
5551 * In this phase, the individual flow blocks are examined
5552 * to determine the Register Banks they use
5555 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5559 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5560 pCodeRegMapLiveRanges(pb);
5562 RemoveUnusedRegisters();
5564 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5565 pCodeRegOptimizeRegUsage(level);
5570 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5575 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5577 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5578 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5579 pcflow = pcflow->next) {
5581 FillFlow(PCFL(pcflow));
5586 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5588 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5589 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5590 pcflow = pcflow->next) {
5592 FlowStats(PCFL(pcflow));
5598 /*-----------------------------------------------------------------*/
5599 /* AnalyzeBanking - Called after the memory addresses have been */
5600 /* assigned to the registers. */
5602 /*-----------------------------------------------------------------*/
5604 void AnalyzeBanking(void)
5608 if(!picIsInitialized()) {
5609 setDefMaxRam(); // Max RAM has not been included, so use default setting
5612 if (!the_pFile) return;
5614 /* Phase x - Flow Analysis - Used Banks
5616 * In this phase, the individual flow blocks are examined
5617 * to determine the Register Banks they use
5623 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5624 // BanksUsedFlow(pb);
5625 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5626 FixRegisterBanking(pb,-1); // cur_bank is unknown
5630 /*-----------------------------------------------------------------*/
5631 /*-----------------------------------------------------------------*/
5632 DEFSETFUNC (resetrIdx)
5634 regs *r = (regs *)item;
5642 /*-----------------------------------------------------------------*/
5643 /* InitRegReuse - Initialises variables for code analyzer */
5644 /*-----------------------------------------------------------------*/
5646 void InitReuseReg(void)
5648 /* Find end of statically allocated variables for start idx */
5649 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5651 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5652 if (r->type != REG_SFR) {
5653 maxIdx += r->size; /* Increment for all statically allocated variables */
5657 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5660 /*-----------------------------------------------------------------*/
5661 /*-----------------------------------------------------------------*/
5662 static unsigned register_reassign(pBlock *pb, unsigned idx)
5666 /* check recursion */
5667 pc = setFirstItem(pb->function_entries);
5673 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5675 if (pb->tregisters) {
5677 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5678 if (r->type == REG_GPR) {
5680 if (r->rIdx < (int)idx) {
5683 if (peakIdx < idx) peakIdx = idx;
5684 sprintf(s,"r0x%02X", r->rIdx);
5685 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5687 r->name = Safe_strdup(s);
5693 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5695 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5696 char *dest = get_op_from_instruction(PCI(pc));
5698 pCode *pcn = findFunction(dest);
5700 register_reassign(pcn->pb,idx);
5709 /*------------------------------------------------------------------*/
5710 /* ReuseReg were call tree permits */
5712 /* Re-allocate the GPR for optimum reuse for a given pblock */
5713 /* eg if a function m() calls function f1() and f2(), where f1 */
5714 /* allocates a local variable vf1 and f2 allocates a local */
5715 /* variable vf2. Then providing f1 and f2 do not call each other */
5716 /* they may share the same general purpose registers for vf1 and */
5718 /* This is done by first setting the the regs rIdx to start after */
5719 /* all the global variables, then walking through the call tree */
5720 /* renaming the registers to match their new idx and incrementng */
5721 /* it as it goes. If a function has already been called it will */
5722 /* only rename the registers if it has already used up those */
5723 /* registers ie rIdx of the function's registers is lower than the */
5724 /* current rIdx. That way the register will not be reused while */
5725 /* still being used by an eariler function call. */
5727 /* Note for this to work the functions need to be declared static. */
5729 /*------------------------------------------------------------------*/
5733 if (!the_pFile) return;
5735 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5736 /* Non static functions can be called from other modules so their registers must reassign */
5737 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5738 register_reassign(pb,peakIdx);
5742 /*-----------------------------------------------------------------*/
5743 /* buildCallTree - look at the flow and extract all of the calls */
5745 /*-----------------------------------------------------------------*/
5747 void buildCallTree(void )
5756 /* Now build the call tree.
5757 First we examine all of the pCodes for functions.
5758 Keep in mind that the function boundaries coincide
5759 with pBlock boundaries.
5761 The algorithm goes something like this:
5762 We have two nested loops. The outer loop iterates
5763 through all of the pBlocks/functions. The inner
5764 loop iterates through all of the pCodes for
5765 a given pBlock. When we begin iterating through
5766 a pBlock, the variable pc_fstart, pCode of the start
5767 of a function, is cleared. We then search for pCodes
5768 of type PC_FUNCTION. When one is encountered, we
5769 initialize pc_fstart to this and at the same time
5770 associate a new pBranch object that signifies a
5771 branch entry. If a return is found, then this signifies
5772 a function exit point. We'll link the pCodes of these
5773 returns to the matching pc_fstart.
5775 When we're done, a doubly linked list of pBranches
5776 will exist. The head of this list is stored in
5777 `the_pFile', which is the meta structure for all
5778 of the pCode. Look at the printCallTree function
5779 on how the pBranches are linked together.
5782 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5783 pCode *pc_fstart=NULL;
5784 for(pc = pb->pcHead; pc; pc = pc->next) {
5786 pCodeFunction *pcf = PCF(pc);
5789 if(STRCASECMP(pcf->fname, "_main") == 0) {
5790 //fprintf(stderr," found main \n");
5791 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5795 pbr = Safe_calloc(1,sizeof(pBranch));
5796 pbr->pc = pc_fstart = pc;
5799 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5801 // Here's a better way of doing the same:
5802 addSet(&pb->function_entries, pc);
5805 // Found an exit point in a function, e.g. return
5806 // (Note, there may be more than one return per function)
5808 pBranchLink(PCF(pc_fstart), pcf);
5810 addSet(&pb->function_exits, pc);
5812 } else if(isCALL(pc)) {
5813 addSet(&pb->function_calls,pc);
5819 /*-----------------------------------------------------------------*/
5820 /* AnalyzepCode - parse the pCode that has been generated and form */
5821 /* all of the logical connections. */
5823 /* Essentially what's done here is that the pCode flow is */
5825 /*-----------------------------------------------------------------*/
5827 void AnalyzepCode(char dbName)
5838 /* Phase 1 - Register allocation and peep hole optimization
5840 * The first part of the analysis is to determine the registers
5841 * that are used in the pCode. Once that is done, the peep rules
5842 * are applied to the code. We continue to loop until no more
5843 * peep rule optimizations are found (or until we exceed the
5844 * MAX_PASSES threshold).
5846 * When done, the required registers will be determined.
5852 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5854 /* First, merge the labels with the instructions */
5855 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5856 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5858 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5859 pBlockMergeLabels(pb);
5862 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5866 changes = OptimizepCode(dbName);
5868 } while(changes && (i++ < MAX_PASSES));
5873 /*-----------------------------------------------------------------*/
5874 /* ispCodeFunction - returns true if *pc is the pCode of a */
5876 /*-----------------------------------------------------------------*/
5877 bool ispCodeFunction(pCode *pc)
5880 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5886 /*-----------------------------------------------------------------*/
5887 /* findFunction - Search for a function by name (given the name) */
5888 /* in the set of all functions that are in a pBlock */
5889 /* (note - I expect this to change because I'm planning to limit */
5890 /* pBlock's to just one function declaration */
5891 /*-----------------------------------------------------------------*/
5892 pCode *findFunction(char *fname)
5899 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5901 pc = setFirstItem(pb->function_entries);
5904 if((pc->type == PC_FUNCTION) &&
5906 (strcmp(fname, PCF(pc)->fname)==0))
5909 pc = setNextItem(pb->function_entries);
5917 void MarkUsedRegisters(set *regset)
5922 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5923 r2 = pic14_regWithIdx(r1->rIdx);
5931 void pBlockStats(FILE *of, pBlock *pb)
5937 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5939 // for now just print the first element of each set
5940 pc = setFirstItem(pb->function_entries);
5942 fprintf(of,";entry: ");
5945 pc = setFirstItem(pb->function_exits);
5947 fprintf(of,";has an exit\n");
5951 pc = setFirstItem(pb->function_calls);
5953 fprintf(of,";functions called:\n");
5956 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5957 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5959 pc = setNextItem(pb->function_calls);
5963 r = setFirstItem(pb->tregisters);
5965 int n = elementsInSet(pb->tregisters);
5967 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5970 fprintf(of,"; %s\n",r->name);
5971 r = setNextItem(pb->tregisters);
5976 /*-----------------------------------------------------------------*/
5977 /*-----------------------------------------------------------------*/
5979 static void sequencepCode(void)
5985 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5987 pb->seq = GpCodeSequenceNumber+1;
5989 for( pc = pb->pcHead; pc; pc = pc->next)
5990 pc->seq = ++GpCodeSequenceNumber;
5996 /*-----------------------------------------------------------------*/
5997 /*-----------------------------------------------------------------*/
5999 set *register_usage(pBlock *pb)
6002 set *registers=NULL;
6003 set *registersInCallPath = NULL;
6005 / * check recursion * /
6007 pc = setFirstItem(pb->function_entries);
6014 if(pc->type != PC_FUNCTION)
6015 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6017 pc = setFirstItem(pb->function_calls);
6018 for( ; pc; pc = setNextItem(pb->function_calls)) {
6020 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6021 char *dest = get_op_from_instruction(PCI(pc));
6023 pcn = findFunction(dest);
6025 registersInCallPath = register_usage(pcn->pb);
6027 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6032 pBlockStats(stderr,pb); // debug
6035 // Mark the registers in this block as used.
6037 MarkUsedRegisters(pb->tregisters);
6038 if(registersInCallPath) {
6039 / * registers were used in the functions this pBlock has called * /
6040 / * so now, we need to see if these collide with the ones we are * /
6043 regs *r1,*r2, *newreg;
6045 DFPRINTF((stderr,"comparing registers\n"));
6047 r1 = setFirstItem(registersInCallPath);
6049 if (r1->type != REG_STK) {
6050 r2 = setFirstItem(pb->tregisters);
6052 while(r2 && (r2->type != REG_STK)) {
6054 if(r2->rIdx == r1->rIdx) {
6055 newreg = pic14_findFreeReg(REG_GPR);
6059 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6063 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6064 r1->rIdx, newreg->rIdx));
6065 r2->rIdx = newreg->rIdx;
6067 r2->name = Safe_strdup(newreg->name);
6071 newreg->wasUsed = 1;
6073 r2 = setNextItem(pb->tregisters);
6077 r1 = setNextItem(registersInCallPath);
6080 / * Collisions have been resolved. Now free the registers in the call path * /
6081 r1 = setFirstItem(registersInCallPath);
6083 newreg = pic14_regWithIdx(r1->rIdx);
6084 if (newreg) newreg->isFree = 1;
6085 r1 = setNextItem(registersInCallPath);
6089 // MarkUsedRegisters(pb->registers);
6091 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6094 DFPRINTF((stderr,"returning regs\n"));
6096 DFPRINTF((stderr,"not returning regs\n"));
6098 DFPRINTF((stderr,"pBlock after register optim.\n"));
6099 pBlockStats(stderr,pb); // debug
6106 /*-----------------------------------------------------------------*/
6107 /* printCallTree - writes the call tree to a file */
6109 /*-----------------------------------------------------------------*/
6110 void pct2(FILE *of,pBlock *pb,int indent)
6114 // set *registersInCallPath = NULL;
6120 return; //recursion ?
6122 pc = setFirstItem(pb->function_entries);
6129 for(i=0;i<indent;i++) // Indentation
6132 if(pc->type == PC_FUNCTION)
6133 fprintf(of,"%s\n",PCF(pc)->fname);
6138 pc = setFirstItem(pb->function_calls);
6139 for( ; pc; pc = setNextItem(pb->function_calls)) {
6141 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6142 char *dest = get_op_from_instruction(PCI(pc));
6144 pcn = findFunction(dest);
6146 pct2(of,pcn->pb,indent+1);
6148 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6156 /*-----------------------------------------------------------------*/
6157 /* printCallTree - writes the call tree to a file */
6159 /*-----------------------------------------------------------------*/
6161 void printCallTree(FILE *of)
6173 fprintf(of, "\npBlock statistics\n");
6174 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6179 fprintf(of,"Call Tree\n");
6180 pbr = the_pFile->functions;
6184 if(!ispCodeFunction(pc))
6185 fprintf(of,"bug in call tree");
6188 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6190 while(pc->next && !ispCodeFunction(pc->next)) {
6192 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6193 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6201 fprintf(of,"\n**************\n\na better call tree\n");
6202 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6207 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6208 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6214 /*-----------------------------------------------------------------*/
6216 /*-----------------------------------------------------------------*/
6218 void InlineFunction(pBlock *pb)
6226 pc = setFirstItem(pb->function_calls);
6228 for( ; pc; pc = setNextItem(pb->function_calls)) {
6231 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6232 pCode *pcp = pc->prev;
6238 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 */
6240 InlineFunction(pcn->pb);
6243 At this point, *pc points to a CALL mnemonic, and
6244 *pcn points to the function that is being called.
6246 To in-line this call, we need to remove the CALL
6247 and RETURN(s), and link the function pCode in with
6254 /* Check if previous instruction was a bit skip */
6255 if (isPCI_BITSKIP(pcp)) {
6257 /* Invert skip instruction and add a goto */
6258 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6260 if(isPCL(pc_call->next)) { // Label pcode
6261 pcl = PCL(pc_call->next);
6262 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6263 pcl = PCL(PCI(pc_call->next)->label->pc);
6265 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6266 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6268 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6271 /* remove callee pBlock from the pBlock linked list */
6272 removepBlock(pcn->pb);
6280 /* Remove the Function pCode */
6281 pct = findNextInstruction(pcn->next);
6283 /* Link the function with the callee */
6284 if (pcp) pcp->next = pcn->next;
6285 pcn->next->prev = pcp;
6287 /* Convert the function name into a label */
6289 pbr = Safe_calloc(1,sizeof(pBranch));
6290 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6292 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6293 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6295 /* turn all of the return's except the last into goto's */
6296 /* check case for 2 instruction pBlocks */
6297 pce = findNextInstruction(pcn->next);
6299 pCode *pce_next = findNextInstruction(pce->next);
6301 if(pce_next == NULL) {
6302 /* found the last return */
6303 pCode *pc_call_next = findNextInstruction(pc_call->next);
6305 //fprintf(stderr,"found last return\n");
6306 //pce->print(stderr,pce);
6307 pce->prev->next = pc_call->next;
6308 pc_call->next->prev = pce->prev;
6309 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6318 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6324 /*-----------------------------------------------------------------*/
6326 /*-----------------------------------------------------------------*/
6328 void InlinepCode(void)
6337 if(!functionInlining)
6340 /* Loop through all of the function definitions and count the
6341 * number of times each one is called */
6342 //fprintf(stderr,"inlining %d\n",__LINE__);
6344 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6346 pc = setFirstItem(pb->function_calls);
6348 for( ; pc; pc = setNextItem(pb->function_calls)) {
6351 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6352 if(pcn && isPCF(pcn)) {
6353 PCF(pcn)->ncalled++;
6356 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6361 //fprintf(stderr,"inlining %d\n",__LINE__);
6363 /* Now, Loop through the function definitions again, but this
6364 * time inline those functions that have only been called once. */
6366 InlineFunction(the_pFile->pbHead);
6367 //fprintf(stderr,"inlining %d\n",__LINE__);
6369 for(pb = the_pFile->pbHead; pb; pb = pb->next)