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);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int functionInlining = 1; /* inline functions if nonzero */
79 int debug_verbose = 0; /* Set true to inundate .asm file */
81 // static int GpCodeSequenceNumber = 1;
84 /* statistics (code size estimation) */
85 static unsigned int pcode_insns = 0;
86 static unsigned int pcode_doubles = 0;
89 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
90 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
92 extern void RemoveUnusedRegisters(void);
93 extern void RegsUnMapLiveRanges(void);
94 extern void BuildFlowTree(pBlock *pb);
95 extern void pCodeRegOptimizeRegUsage(int level);
96 extern int picIsInitialized(void);
97 extern const char *pCodeOpType(pCodeOp *pcop);
99 /****************************************************************/
100 /* Forward declarations */
101 /****************************************************************/
103 void unlinkpCode(pCode *pc);
105 static void genericAnalyze(pCode *pc);
106 static void AnalyzeGOTO(pCode *pc);
107 static void AnalyzeSKIP(pCode *pc);
108 static void AnalyzeRETURN(pCode *pc);
111 static void genericDestruct(pCode *pc);
112 static void genericPrint(FILE *of,pCode *pc);
114 static void pCodePrintLabel(FILE *of, pCode *pc);
115 static void pCodePrintFunction(FILE *of, pCode *pc);
116 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
117 static char *get_op_from_instruction( pCodeInstruction *pcc);
118 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
119 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
120 int pCodePeepMatchRule(pCode *pc);
121 void pBlockStats(FILE *of, pBlock *pb);
122 pBlock *newpBlock(void);
123 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
124 void pCodeRegMapLiveRanges(pBlock *pb);
126 pBranch * pBranchAppend(pBranch *h, pBranch *n);
129 /****************************************************************/
130 /* PIC Instructions */
131 /****************************************************************/
133 pCodeInstruction pciADDWF = {
134 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
147 1,0, // dest, bit instruction
149 0, // literal operand
151 (PCC_W | PCC_REGISTER), // inCond
152 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
155 pCodeInstruction pciADDFW = {
156 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
169 0,0, // dest, bit instruction
171 0, // literal operand
173 (PCC_W | PCC_REGISTER), // inCond
174 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
177 pCodeInstruction pciADDLW = {
178 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
191 0,0, // dest, bit instruction
193 1, // literal operand
195 (PCC_W | PCC_LITERAL), // inCond
196 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
199 pCodeInstruction pciANDLW = {
200 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
213 0,0, // dest, bit instruction
215 1, // literal operand
217 (PCC_W | PCC_LITERAL), // inCond
218 (PCC_W | PCC_Z) // outCond
221 pCodeInstruction pciANDWF = {
222 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
235 1,0, // dest, bit instruction
237 0, // literal operand
239 (PCC_W | PCC_REGISTER), // inCond
240 (PCC_REGISTER | PCC_Z) // outCond
243 pCodeInstruction pciANDFW = {
244 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
257 0,0, // dest, bit instruction
259 0, // literal operand
261 (PCC_W | PCC_REGISTER), // inCond
262 (PCC_W | PCC_Z) // outCond
265 pCodeInstruction pciBCF = {
266 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
279 1,1, // dest, bit instruction
281 0, // literal operand
283 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
284 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
287 pCodeInstruction pciBSF = {
288 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
301 1,1, // dest, bit instruction
303 0, // literal operand
305 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
306 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
309 pCodeInstruction pciBTFSC = {
310 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
323 0,1, // dest, bit instruction
325 0, // literal operand
327 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
331 pCodeInstruction pciBTFSS = {
332 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
345 0,1, // dest, bit instruction
347 0, // literal operand
349 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
353 pCodeInstruction pciCALL = {
354 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
367 0,0, // dest, bit instruction
369 0, // literal operand
371 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
372 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
375 pCodeInstruction pciCOMF = {
376 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
389 1,0, // dest, bit instruction
391 0, // literal operand
393 PCC_REGISTER, // inCond
394 PCC_REGISTER | PCC_Z // outCond
397 pCodeInstruction pciCOMFW = {
398 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
411 0,0, // dest, bit instruction
413 0, // literal operand
415 PCC_REGISTER, // inCond
416 PCC_W | PCC_Z // outCond
419 pCodeInstruction pciCLRF = {
420 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
433 0,0, // dest, bit instruction
435 0, // literal operand
438 PCC_REGISTER | PCC_Z // outCond
441 pCodeInstruction pciCLRW = {
442 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
455 0,0, // dest, bit instruction
457 0, // literal operand
460 PCC_W | PCC_Z // outCond
463 pCodeInstruction pciCLRWDT = {
464 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
477 0,0, // dest, bit instruction
479 0, // literal operand
485 pCodeInstruction pciDECF = {
486 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
499 1,0, // dest, bit instruction
501 0, // literal operand
503 PCC_REGISTER, // inCond
504 PCC_REGISTER | PCC_Z // outCond
507 pCodeInstruction pciDECFW = {
508 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
521 0,0, // dest, bit instruction
523 0, // literal operand
525 PCC_REGISTER, // inCond
526 PCC_W | PCC_Z // outCond
529 pCodeInstruction pciDECFSZ = {
530 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
543 1,0, // dest, bit instruction
545 0, // literal operand
546 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
547 PCC_REGISTER, // inCond
548 PCC_REGISTER | PCC_Z // outCond
551 pCodeInstruction pciDECFSZW = {
552 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
565 0,0, // dest, bit instruction
567 0, // literal operand
568 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
569 PCC_REGISTER, // inCond
570 PCC_W | PCC_Z // outCond
573 pCodeInstruction pciGOTO = {
574 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
587 0,0, // dest, bit instruction
589 0, // literal operand
595 pCodeInstruction pciINCF = {
596 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
609 1,0, // dest, bit instruction
611 0, // literal operand
613 PCC_REGISTER, // inCond
614 PCC_REGISTER | PCC_Z // outCond
617 pCodeInstruction pciINCFW = {
618 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
631 0,0, // dest, bit instruction
633 0, // literal operand
635 PCC_REGISTER, // inCond
636 PCC_W | PCC_Z // outCond
639 pCodeInstruction pciINCFSZ = {
640 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
653 1,0, // dest, bit instruction
655 0, // literal operand
656 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
657 PCC_REGISTER, // inCond
658 PCC_REGISTER | PCC_Z // outCond
661 pCodeInstruction pciINCFSZW = {
662 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
675 0,0, // dest, bit instruction
677 0, // literal operand
678 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
679 PCC_REGISTER, // inCond
680 PCC_W | PCC_Z // outCond
683 pCodeInstruction pciIORWF = {
684 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
697 1,0, // dest, bit instruction
699 0, // literal operand
701 (PCC_W | PCC_REGISTER), // inCond
702 (PCC_REGISTER | PCC_Z) // outCond
705 pCodeInstruction pciIORFW = {
706 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
719 0,0, // dest, bit instruction
721 0, // literal operand
723 (PCC_W | PCC_REGISTER), // inCond
724 (PCC_W | PCC_Z) // outCond
727 pCodeInstruction pciIORLW = {
728 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
741 0,0, // dest, bit instruction
743 1, // literal operand
745 (PCC_W | PCC_LITERAL), // inCond
746 (PCC_W | PCC_Z) // outCond
749 pCodeInstruction pciMOVF = {
750 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
763 1,0, // dest, bit instruction
765 0, // literal operand
767 PCC_REGISTER, // inCond
771 pCodeInstruction pciMOVFW = {
772 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
785 0,0, // dest, bit instruction
787 0, // literal operand
789 PCC_REGISTER, // inCond
790 (PCC_W | PCC_Z) // outCond
793 pCodeInstruction pciMOVWF = {
794 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
807 0,0, // dest, bit instruction
809 0, // literal operand
812 PCC_REGISTER // outCond
815 pCodeInstruction pciMOVLW = {
816 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
828 0,0, // dest, bit instruction
830 1, // literal operand
832 (PCC_NONE | PCC_LITERAL), // inCond
836 pCodeInstruction pciNOP = {
837 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
849 0,0, // dest, bit instruction
851 0, // literal operand
857 pCodeInstruction pciRETFIE = {
858 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
871 0,0, // dest, bit instruction
873 0, // literal operand
876 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
879 pCodeInstruction pciRETLW = {
880 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
893 0,0, // dest, bit instruction
895 1, // literal operand
897 PCC_LITERAL, // inCond
898 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
901 pCodeInstruction pciRETURN = {
902 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
915 0,0, // dest, bit instruction
917 0, // literal operand
919 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
920 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
923 pCodeInstruction pciRLF = {
924 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
937 1,0, // dest, bit instruction
939 0, // literal operand
941 (PCC_C | PCC_REGISTER), // inCond
942 (PCC_REGISTER | PCC_C ) // outCond
945 pCodeInstruction pciRLFW = {
946 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
959 0,0, // dest, bit instruction
961 0, // literal operand
963 (PCC_C | PCC_REGISTER), // inCond
964 (PCC_W | PCC_C) // outCond
967 pCodeInstruction pciRRF = {
968 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
981 1,0, // dest, bit instruction
983 0, // literal operand
985 (PCC_C | PCC_REGISTER), // inCond
986 (PCC_REGISTER | PCC_C) // outCond
989 pCodeInstruction pciRRFW = {
990 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1003 0,0, // dest, bit instruction
1004 0,0, // branch, skip
1005 0, // literal operand
1007 (PCC_C | PCC_REGISTER), // inCond
1008 (PCC_W | PCC_C) // outCond
1011 pCodeInstruction pciSUBWF = {
1012 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1018 NULL, // from branch
1025 1,0, // dest, bit instruction
1026 0,0, // branch, skip
1027 0, // literal operand
1029 (PCC_W | PCC_REGISTER), // inCond
1030 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1033 pCodeInstruction pciSUBFW = {
1034 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1040 NULL, // from branch
1047 0,0, // dest, bit instruction
1048 0,0, // branch, skip
1049 0, // literal operand
1051 (PCC_W | PCC_REGISTER), // inCond
1052 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1055 pCodeInstruction pciSUBLW = {
1056 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1062 NULL, // from branch
1069 0,0, // dest, bit instruction
1070 0,0, // branch, skip
1071 1, // literal operand
1073 (PCC_W | PCC_LITERAL), // inCond
1074 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1077 pCodeInstruction pciSWAPF = {
1078 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1084 NULL, // from branch
1091 1,0, // dest, bit instruction
1092 0,0, // branch, skip
1093 0, // literal operand
1095 (PCC_REGISTER), // inCond
1096 (PCC_REGISTER) // outCond
1099 pCodeInstruction pciSWAPFW = {
1100 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1106 NULL, // from branch
1113 0,0, // dest, bit instruction
1114 0,0, // branch, skip
1115 0, // literal operand
1117 (PCC_REGISTER), // inCond
1121 pCodeInstruction pciTRIS = {
1122 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1128 NULL, // from branch
1135 0,0, // dest, bit instruction
1136 0,0, // branch, skip
1137 0, // literal operand
1139 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1140 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1143 pCodeInstruction pciXORWF = {
1144 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1150 NULL, // from branch
1157 1,0, // dest, bit instruction
1158 0,0, // branch, skip
1159 0, // literal operand
1161 (PCC_W | PCC_REGISTER), // inCond
1162 (PCC_REGISTER | PCC_Z) // outCond
1165 pCodeInstruction pciXORFW = {
1166 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1172 NULL, // from branch
1179 0,0, // dest, bit instruction
1180 0,0, // branch, skip
1181 0, // literal operand
1183 (PCC_W | PCC_REGISTER), // inCond
1184 (PCC_W | PCC_Z) // outCond
1187 pCodeInstruction pciXORLW = {
1188 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1194 NULL, // from branch
1201 0,0, // dest, bit instruction
1202 0,0, // branch, skip
1203 1, // literal operand
1205 (PCC_W | PCC_LITERAL), // inCond
1206 (PCC_W | PCC_Z) // outCond
1210 pCodeInstruction pciBANKSEL = {
1211 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1217 NULL, // from branch
1224 0,0, // dest, bit instruction
1225 0,0, // branch, skip
1226 0, // literal operand
1232 pCodeInstruction pciPAGESEL = {
1233 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1239 NULL, // from branch
1246 0,0, // dest, bit instruction
1247 0,0, // branch, skip
1248 0, // literal operand
1254 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1257 /*-----------------------------------------------------------------*/
1258 /* return a unique ID number to assist pCodes debuging */
1259 /*-----------------------------------------------------------------*/
1260 unsigned PCodeID(void) {
1261 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1263 static unsigned int stop;
1264 if (pcodeId == 1448)
1265 stop++; // Place break point here
1270 #ifdef HAVE_VSNPRINTF
1271 // Alas, vsnprintf is not ANSI standard, and does not exist
1272 // on Solaris (and probably other non-Gnu flavored Unixes).
1274 /*-----------------------------------------------------------------*/
1275 /* SAFE_snprintf - like snprintf except the string pointer is */
1276 /* after the string has been printed to. This is */
1277 /* useful for printing to string as though if it */
1278 /* were a stream. */
1279 /*-----------------------------------------------------------------*/
1280 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1288 va_start(val, format);
1290 vsnprintf(*str, *size, format, val);
1295 if((size_t)len > *size) {
1296 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1297 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1305 #else // HAVE_VSNPRINTF
1307 // This version is *not* safe, despite the name.
1309 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1313 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1318 va_start(val, format);
1320 vsprintf(buffer, format, val);
1323 len = strlen(buffer);
1325 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1326 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1329 strcpy(*str, buffer);
1335 #endif // HAVE_VSNPRINTF
1338 extern void initStack(int base_address, int size);
1339 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1340 extern regs *allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias);
1341 extern void init_pic(char *);
1343 void pCodeInitRegisters(void)
1345 static int initialized=0;
1346 int shareBankAddress,stkSize;
1352 init_pic(port->processor);
1353 /* FIXME - some PIC ICs like 16C7X which do not have a shared bank
1354 * need a different approach.
1355 * The fixed address might not be needed anyway, possibly the
1356 * linker will assign udata_shr sections correctly... */
1357 shareBankAddress = pic14_getSharebankAddress();
1358 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1359 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1360 * (used for interrupts) to fit into the shared portion of the
1362 stkSize = pic14_getSharebankSize()-3;
1363 /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1364 initStack(shareBankAddress, stkSize);
1366 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1367 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1368 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1369 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1370 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1371 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1373 pc_status.rIdx = IDX_STATUS;
1374 pc_fsr.rIdx = IDX_FSR;
1375 pc_indf.rIdx = IDX_INDF;
1376 pc_intcon.rIdx = IDX_INTCON;
1377 pc_pcl.rIdx = IDX_PCL;
1378 pc_pclath.rIdx = IDX_PCLATH;
1380 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1381 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1382 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1384 pc_wsave.rIdx = pc_wsave.r->rIdx;
1385 pc_ssave.rIdx = pc_ssave.r->rIdx;
1386 pc_psave.rIdx = pc_psave.r->rIdx;
1388 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1389 pc_wsave.r->address = shareBankAddress-stkSize;
1390 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1391 pc_ssave.r->address = shareBankAddress-stkSize-1;
1392 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1393 pc_psave.r->address = shareBankAddress-stkSize-2;
1395 /* probably should put this in a separate initialization routine */
1396 pb_dead_pcodes = newpBlock();
1400 /*-----------------------------------------------------------------*/
1401 /* mnem2key - convert a pic mnemonic into a hash key */
1402 /* (BTW - this spreads the mnemonics quite well) */
1404 /*-----------------------------------------------------------------*/
1406 int mnem2key(unsigned char const *mnem)
1415 key += toupper(*mnem++) +1;
1419 return (key & 0x1f);
1423 void pic14initMnemonics(void)
1428 pCodeInstruction *pci;
1430 if(mnemonics_initialized)
1433 //FIXME - probably should NULL out the array before making the assignments
1434 //since we check the array contents below this initialization.
1436 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1437 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1438 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1439 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1440 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1441 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1442 pic14Mnemonics[POC_BCF] = &pciBCF;
1443 pic14Mnemonics[POC_BSF] = &pciBSF;
1444 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1445 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1446 pic14Mnemonics[POC_CALL] = &pciCALL;
1447 pic14Mnemonics[POC_COMF] = &pciCOMF;
1448 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1449 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1450 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1451 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1452 pic14Mnemonics[POC_DECF] = &pciDECF;
1453 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1454 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1455 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1456 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1457 pic14Mnemonics[POC_INCF] = &pciINCF;
1458 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1459 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1460 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1461 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1462 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1463 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1464 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1465 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1466 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1467 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1468 pic14Mnemonics[POC_NOP] = &pciNOP;
1469 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1470 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1471 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1472 pic14Mnemonics[POC_RLF] = &pciRLF;
1473 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1474 pic14Mnemonics[POC_RRF] = &pciRRF;
1475 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1476 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1477 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1478 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1479 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1480 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1481 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1482 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1483 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1484 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1485 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1486 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1488 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1489 if(pic14Mnemonics[i])
1490 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1491 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1494 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1495 pci = hTabNextItem(pic14MnemonicsHash, &key);
1498 mnemonics_initialized = 1;
1501 int getpCodePeepCommand(char *cmd);
1503 int getpCode(char *mnem,unsigned dest)
1506 pCodeInstruction *pci;
1507 int key = mnem2key((unsigned char *)mnem);
1509 if(!mnemonics_initialized)
1510 pic14initMnemonics();
1512 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1516 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1517 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1521 pci = hTabNextItemWK (pic14MnemonicsHash);
1528 /*-----------------------------------------------------------------*
1529 * pic14initpCodePeepCommands
1531 *-----------------------------------------------------------------*/
1532 void pic14initpCodePeepCommands(void)
1540 hTabAddItem(&pic14pCodePeepCommandsHash,
1541 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1543 } while (peepCommands[i].cmd);
1545 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1548 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1549 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1554 /*-----------------------------------------------------------------
1557 *-----------------------------------------------------------------*/
1559 int getpCodePeepCommand(char *cmd)
1563 int key = mnem2key((unsigned char *)cmd);
1566 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1569 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1570 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1574 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1581 char getpBlock_dbName(pBlock *pb)
1587 return pb->cmemmap->dbName;
1591 void pBlockConvert2ISR(pBlock *pb)
1602 /*-----------------------------------------------------------------*/
1603 /* movepBlock2Head - given the dbname of a pBlock, move all */
1604 /* instances to the front of the doubly linked */
1605 /* list of pBlocks */
1606 /*-----------------------------------------------------------------*/
1608 void movepBlock2Head(char dbName)
1615 pb = the_pFile->pbHead;
1619 if(getpBlock_dbName(pb) == dbName) {
1620 pBlock *pbn = pb->next;
1621 pb->next = the_pFile->pbHead;
1622 the_pFile->pbHead->prev = pb;
1623 the_pFile->pbHead = pb;
1626 pb->prev->next = pbn;
1628 // If the pBlock that we just moved was the last
1629 // one in the link of all of the pBlocks, then we
1630 // need to point the tail to the block just before
1631 // the one we moved.
1632 // Note: if pb->next is NULL, then pb must have
1633 // been the last pBlock in the chain.
1636 pbn->prev = pb->prev;
1638 the_pFile->pbTail = pb->prev;
1649 void copypCode(FILE *of, char dbName)
1653 if(!of || !the_pFile)
1656 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1657 if(getpBlock_dbName(pb) == dbName) {
1666 void resetpCodeStatistics (void)
1668 pcode_insns = pcode_doubles = 0;
1671 void dumppCodeStatistics (FILE *of)
1673 /* dump statistics */
1675 fprintf (of, ";\tcode size estimation:\n");
1676 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1680 void pcode_test(void)
1683 DFPRINTF((stderr,"pcode is alive!\n"));
1693 /* create the file name */
1694 strcpy(buffer,dstFileName);
1695 strcat(buffer,".p");
1697 if( !(pFile = fopen(buffer, "w" ))) {
1698 werror(E_FILE_OPEN_ERR,buffer);
1702 fprintf(pFile,"pcode dump\n\n");
1704 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1705 fprintf(pFile,"\n\tNew pBlock\n\n");
1707 fprintf(pFile,"%s",pb->cmemmap->sname);
1709 fprintf(pFile,"internal pblock");
1711 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1712 printpBlock(pFile,pb);
1716 /*-----------------------------------------------------------------*/
1717 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1718 /* ister, RegCond will return the bit being referenced. */
1720 /* fixme - why not just OR in the pcop bit field */
1721 /*-----------------------------------------------------------------*/
1723 static int RegCond(pCodeOp *pcop)
1729 if (pcop->type == PO_GPR_BIT) {
1730 char *name = pcop->name;
1732 name = PCOR(pcop)->r->name;
1733 if (strcmp(name, pc_status.pcop.name) == 0)
1735 switch(PCORB(pcop)->bit) {
1749 /*-----------------------------------------------------------------*/
1750 /* newpCode - create and return a newly initialized pCode */
1752 /* fixme - rename this */
1754 /* The purpose of this routine is to create a new Instruction */
1755 /* pCode. This is called by gen.c while the assembly code is being */
1759 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1760 /* (note that the op is analogous to but not the */
1761 /* same thing as the opcode of the instruction.) */
1762 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1765 /* a pointer to the new malloc'd pCode is returned. */
1769 /*-----------------------------------------------------------------*/
1770 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1772 pCodeInstruction *pci ;
1774 if(!mnemonics_initialized)
1775 pic14initMnemonics();
1777 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1779 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1780 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1781 pci->pc.id = PCodeID();
1784 if(pci->inCond & PCC_EXAMINE_PCOP)
1785 pci->inCond |= RegCond(pcop);
1787 if(pci->outCond & PCC_EXAMINE_PCOP)
1788 pci->outCond |= RegCond(pcop);
1790 pci->pc.prev = pci->pc.next = NULL;
1791 return (pCode *)pci;
1794 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1800 /*-----------------------------------------------------------------*/
1801 /* newpCodeWild - create a "wild" as in wild card pCode */
1803 /* Wild pcodes are used during the peep hole optimizer to serve */
1804 /* as place holders for any instruction. When a snippet of code is */
1805 /* compared to a peep hole rule, the wild card opcode will match */
1806 /* any instruction. However, the optional operand and label are */
1807 /* additional qualifiers that must also be matched before the */
1808 /* line (of assembly code) is declared matched. Note that the */
1809 /* operand may be wild too. */
1811 /* Note, a wild instruction is specified just like a wild var: */
1812 /* %4 ; A wild instruction, */
1813 /* See the peeph.def file for additional examples */
1815 /*-----------------------------------------------------------------*/
1817 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1822 pcw = Safe_calloc(1,sizeof(pCodeWild));
1824 pcw->pci.pc.type = PC_WILD;
1825 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1826 pcw->id = PCodeID();
1827 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1828 pcw->pci.pc.pb = NULL;
1830 // pcw->pci.pc.analyze = genericAnalyze;
1831 pcw->pci.pc.destruct = genericDestruct;
1832 pcw->pci.pc.print = genericPrint;
1834 pcw->id = pCodeID; // this is the 'n' in %n
1835 pcw->operand = optional_operand;
1836 pcw->label = optional_label;
1838 pcw->mustBeBitSkipInst = 0;
1839 pcw->mustNotBeBitSkipInst = 0;
1840 pcw->invertBitSkipInst = 0;
1842 return ( (pCode *)pcw);
1846 /*-----------------------------------------------------------------*/
1847 /* newPcodeInlineP - create a new pCode from a char string */
1848 /*-----------------------------------------------------------------*/
1851 pCode *newpCodeInlineP(char *cP)
1856 pcc = Safe_calloc(1,sizeof(pCodeComment));
1858 pcc->pc.type = PC_INLINE;
1859 pcc->pc.prev = pcc->pc.next = NULL;
1860 pcc->pc.id = PCodeID();
1861 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1864 // pcc->pc.analyze = genericAnalyze;
1865 pcc->pc.destruct = genericDestruct;
1866 pcc->pc.print = genericPrint;
1869 pcc->comment = Safe_strdup(cP);
1871 pcc->comment = NULL;
1873 return ( (pCode *)pcc);
1877 /*-----------------------------------------------------------------*/
1878 /* newPcodeCharP - create a new pCode from a char string */
1879 /*-----------------------------------------------------------------*/
1881 pCode *newpCodeCharP(char *cP)
1886 pcc = Safe_calloc(1,sizeof(pCodeComment));
1888 pcc->pc.type = PC_COMMENT;
1889 pcc->pc.prev = pcc->pc.next = NULL;
1890 pcc->pc.id = PCodeID();
1891 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1894 // pcc->pc.analyze = genericAnalyze;
1895 pcc->pc.destruct = genericDestruct;
1896 pcc->pc.print = genericPrint;
1899 pcc->comment = Safe_strdup(cP);
1901 pcc->comment = NULL;
1903 return ( (pCode *)pcc);
1907 /*-----------------------------------------------------------------*/
1908 /* newpCodeFunction - */
1909 /*-----------------------------------------------------------------*/
1912 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1916 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1917 //_ALLOC(pcf,sizeof(pCodeFunction));
1919 pcf->pc.type = PC_FUNCTION;
1920 pcf->pc.prev = pcf->pc.next = NULL;
1921 pcf->pc.id = PCodeID();
1922 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1925 // pcf->pc.analyze = genericAnalyze;
1926 pcf->pc.destruct = genericDestruct;
1927 pcf->pc.print = pCodePrintFunction;
1932 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1933 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1934 strcpy(pcf->modname,mod);
1936 pcf->modname = NULL;
1939 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1940 pcf->fname = Safe_calloc(1,strlen(f)+1);
1941 strcpy(pcf->fname,f);
1945 pcf->isPublic = (unsigned)isPublic;
1947 return ( (pCode *)pcf);
1951 /*-----------------------------------------------------------------*/
1953 /*-----------------------------------------------------------------*/
1954 void destructpCodeFlow(pCode *pc)
1956 if(!pc || !isPCFL(pc))
1965 deleteSet(&PCFL(pc)->registers);
1966 deleteSet(&PCFL(pc)->from);
1967 deleteSet(&PCFL(pc)->to);
1972 pCode *newpCodeFlow(void )
1976 //_ALLOC(pcflow,sizeof(pCodeFlow));
1977 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1979 pcflow->pc.type = PC_FLOW;
1980 pcflow->pc.prev = pcflow->pc.next = NULL;
1981 pcflow->pc.pb = NULL;
1983 // pcflow->pc.analyze = genericAnalyze;
1984 pcflow->pc.destruct = destructpCodeFlow;
1985 pcflow->pc.print = genericPrint;
1987 pcflow->pc.seq = GpcFlowSeq++;
1989 pcflow->from = pcflow->to = NULL;
1991 pcflow->inCond = PCC_NONE;
1992 pcflow->outCond = PCC_NONE;
1994 pcflow->firstBank = 'U'; /* Undetermined */
1995 pcflow->lastBank = 'U'; /* Undetermined */
1997 pcflow->FromConflicts = 0;
1998 pcflow->ToConflicts = 0;
2002 pcflow->registers = newSet();
2004 return ( (pCode *)pcflow);
2008 /*-----------------------------------------------------------------*/
2009 /*-----------------------------------------------------------------*/
2010 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2012 pCodeFlowLink *pcflowLink;
2014 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2016 pcflowLink->pcflow = pcflow;
2017 pcflowLink->bank_conflict = 0;
2022 /*-----------------------------------------------------------------*/
2023 /* newpCodeCSource - create a new pCode Source Symbol */
2024 /*-----------------------------------------------------------------*/
2026 pCode *newpCodeCSource(int ln, char *f, const char *l)
2031 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2033 pccs->pc.type = PC_CSOURCE;
2034 pccs->pc.prev = pccs->pc.next = NULL;
2035 pccs->pc.id = PCodeID();
2038 pccs->pc.destruct = genericDestruct;
2039 pccs->pc.print = genericPrint;
2041 pccs->line_number = ln;
2043 pccs->line = Safe_strdup(l);
2048 pccs->file_name = Safe_strdup(f);
2050 pccs->file_name = NULL;
2052 return ( (pCode *)pccs);
2056 /*******************************************************************/
2057 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2058 /* added by VR 6-Jun-2003 */
2059 /*******************************************************************/
2061 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2068 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2069 pcad->pci.pc.type = PC_ASMDIR;
2070 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2071 pcad->pci.pc.pb = NULL;
2072 pcad->pci.pc.destruct = genericDestruct;
2073 pcad->pci.pc.print = genericPrint;
2075 if(asdir && *asdir) {
2077 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2079 pcad->directive = Safe_strdup( asdir );
2082 va_start(ap, argfmt);
2084 memset(buffer, 0, sizeof(buffer));
2085 if(argfmt && *argfmt)
2086 vsprintf(buffer, argfmt, ap);
2090 while(isspace((unsigned char)*lbp))lbp++;
2093 pcad->arg = Safe_strdup( lbp );
2095 return ((pCode *)pcad);
2098 /*-----------------------------------------------------------------*/
2099 /* pCodeLabelDestruct - free memory used by a label. */
2100 /*-----------------------------------------------------------------*/
2101 static void pCodeLabelDestruct(pCode *pc)
2107 if((pc->type == PC_LABEL) && PCL(pc)->label)
2108 free(PCL(pc)->label);
2114 pCode *newpCodeLabel(char *name, int key)
2120 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2122 pcl->pc.type = PC_LABEL;
2123 pcl->pc.prev = pcl->pc.next = NULL;
2124 pcl->pc.id = PCodeID();
2125 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2128 // pcl->pc.analyze = genericAnalyze;
2129 pcl->pc.destruct = pCodeLabelDestruct;
2130 pcl->pc.print = pCodePrintLabel;
2136 sprintf(s,"_%05d_DS_",key);
2141 pcl->label = Safe_strdup(s);
2143 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2144 return ( (pCode *)pcl);
2149 /*-----------------------------------------------------------------*/
2150 /* newpBlock - create and return a pointer to a new pBlock */
2151 /*-----------------------------------------------------------------*/
2152 pBlock *newpBlock(void)
2157 PpB = Safe_calloc(1,sizeof(pBlock) );
2158 PpB->next = PpB->prev = NULL;
2160 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2161 PpB->tregisters = NULL;
2163 PpB->FlowTree = NULL;
2169 /*-----------------------------------------------------------------*/
2170 /* newpCodeChain - create a new chain of pCodes */
2171 /*-----------------------------------------------------------------*
2173 * This function will create a new pBlock and the pointer to the
2174 * pCode that is passed in will be the first pCode in the block.
2175 *-----------------------------------------------------------------*/
2178 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2181 pBlock *pB = newpBlock();
2183 pB->pcHead = pB->pcTail = pc;
2190 /*-----------------------------------------------------------------*/
2191 /* newpCodeOpLabel - Create a new label given the key */
2192 /* Note, a negative key means that the label is part of wild card */
2193 /* (and hence a wild card label) used in the pCodePeep */
2194 /* optimizations). */
2195 /*-----------------------------------------------------------------*/
2197 pCodeOp *newpCodeOpLabel(char *name, int key)
2200 static int label_key=-1;
2204 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2205 pcop->type = PO_LABEL;
2210 sprintf(s=buffer,"_%05d_DS_",key);
2212 s = name, key = label_key--;
2214 PCOLAB(pcop)->offset = 0;
2216 pcop->name = Safe_strdup(s);
2218 ((pCodeOpLabel *)pcop)->key = key;
2220 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2224 /*-----------------------------------------------------------------*/
2225 /*-----------------------------------------------------------------*/
2226 pCodeOp *newpCodeOpLit(int lit)
2232 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2233 pcop->type = PO_LITERAL;
2237 sprintf(s,"0x%02x", (unsigned char)lit);
2239 pcop->name = Safe_strdup(s);
2242 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2247 /*-----------------------------------------------------------------*/
2248 /*-----------------------------------------------------------------*/
2249 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2253 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2254 pcop->type = PO_IMMEDIATE;
2257 pcop->name = Safe_strdup(name);
2260 r = dirregWithName(name);
2264 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2265 PCOI(pcop)->rIdx = r->rIdx;
2267 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2268 PCOI(pcop)->rIdx = -1;
2270 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2275 PCOI(pcop)->index = index;
2276 PCOI(pcop)->offset = offset;
2277 PCOI(pcop)->_const = code_space;
2278 PCOI(pcop)->_function = is_func;
2283 /*-----------------------------------------------------------------*/
2284 /*-----------------------------------------------------------------*/
2285 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2291 if(!pcwb || !subtype) {
2292 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2296 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2297 pcop->type = PO_WILD;
2298 sprintf(s,"%%%d",id);
2299 pcop->name = Safe_strdup(s);
2301 PCOW(pcop)->id = id;
2302 PCOW(pcop)->pcwb = pcwb;
2303 PCOW(pcop)->subtype = subtype;
2304 PCOW(pcop)->matched = NULL;
2308 /*-----------------------------------------------------------------*/
2309 /* Find a symbol with matching name */
2310 /*-----------------------------------------------------------------*/
2311 static symbol *symFindWithName(memmap * map, const char *name)
2315 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2316 if (sym->rname && (strcmp(sym->rname,name)==0))
2322 /*-----------------------------------------------------------------*/
2323 /*-----------------------------------------------------------------*/
2324 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2329 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2330 pcop->type = PO_GPR_BIT;
2332 PCORB(pcop)->bit = ibit;
2333 PCORB(pcop)->inBitSpace = inBitSpace;
2335 if (name) r = regFindWithName(name);
2337 // Register has not been allocated - check for symbol information
2339 sym = symFindWithName(bit, name);
2340 if (!sym) sym = symFindWithName(sfrbit, name);
2341 if (!sym) sym = symFindWithName(sfr, name);
2342 if (!sym) sym = symFindWithName(reg, name);
2343 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2344 // XXX: This ignores nesting levels, but works for globals...
2345 if (!sym) sym = findSym(SymbolTab, NULL, name);
2346 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2348 r = allocNewDirReg(sym->etype,name);
2354 PCOR(pcop)->rIdx = r->rIdx;
2356 pcop->name = Safe_strdup(name);
2357 PCOR(pcop)->r = NULL;
2358 PCOR(pcop)->rIdx = 0;
2364 pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2370 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2371 pcop->name = reg->name;
2372 pcop->type = PO_GPR_BIT;
2373 PCORB(pcop)->bit = ibit;
2374 PCORB(pcop)->inBitSpace = inBitSpace;
2375 PCOR(pcop)->r = reg;
2376 PCOR(pcop)->index = 0;
2377 PCOR(pcop)->rIdx = reg->rIdx;
2382 /*-----------------------------------------------------------------*
2383 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2385 * If rIdx >=0 then a specific register from the set of registers
2386 * will be selected. If rIdx <0, then a new register will be searched
2388 *-----------------------------------------------------------------*/
2390 pCodeOp *newpCodeOpReg(int rIdx)
2394 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2399 PCOR(pcop)->rIdx = rIdx;
2400 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2402 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2405 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2409 pcop->type = PCOR(pcop)->r->pc_type;
2414 pCodeOp *newpCodeOpRegFromStr(char *name)
2418 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2419 PCOR(pcop)->r = allocRegByName(name, 1);
2420 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2421 pcop->type = PCOR(pcop)->r->pc_type;
2422 pcop->name = PCOR(pcop)->r->name;
2427 pCodeOp *newpCodeOpStr(char *name)
2431 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2432 pcop->type = PO_STR;
2433 pcop->name = Safe_strdup(name);
2435 PCOS(pcop)->isPublic = 0;
2441 /*-----------------------------------------------------------------*/
2442 /*-----------------------------------------------------------------*/
2444 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2451 pcop = newpCodeOpBit(name, -1,0);
2455 pcop = newpCodeOpLit(-1);
2459 pcop = newpCodeOpLabel(NULL,-1);
2463 pcop = newpCodeOpReg(-1);
2466 case PO_GPR_POINTER:
2467 case PO_GPR_REGISTER:
2469 pcop = newpCodeOpRegFromStr(name);
2471 pcop = newpCodeOpReg(-1);
2475 pcop = newpCodeOpStr(name);
2479 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2482 pcop->name = Safe_strdup(name);
2490 /*-----------------------------------------------------------------*/
2491 /*-----------------------------------------------------------------*/
2492 void pCodeConstString(char *name, char *value)
2497 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2502 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2506 sprintf(buffer,"; %s = %s",name,value);
2507 for (i=strlen(buffer); i--; ) {
2508 unsigned char c = buffer[i];
2509 if (c=='\r' || c=='\n') {
2510 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2512 if (c=='\r') buffer[i+1] = 'r';
2513 else if (c=='\n') buffer[i+1] = 'n';
2517 addpCode2pBlock(pb,newpCodeCharP(buffer));
2518 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2521 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2527 /*-----------------------------------------------------------------*/
2528 /*-----------------------------------------------------------------*/
2529 void pCodeReadCodeTable(void)
2533 fprintf(stderr, " %s\n",__FUNCTION__);
2535 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2539 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2540 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2541 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2542 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2544 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2545 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2546 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2547 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2552 /*-----------------------------------------------------------------*/
2553 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2554 /*-----------------------------------------------------------------*/
2555 void addpCode2pBlock(pBlock *pb, pCode *pc)
2562 /* If this is the first pcode to be added to a block that
2563 * was initialized with a NULL pcode, then go ahead and
2564 * make this pcode the head and tail */
2565 pb->pcHead = pb->pcTail = pc;
2568 pb->pcTail->next = pc;
2570 pc->prev = pb->pcTail;
2577 /*-----------------------------------------------------------------*/
2578 /* addpBlock - place a pBlock into the pFile */
2579 /*-----------------------------------------------------------------*/
2580 void addpBlock(pBlock *pb)
2582 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2585 /* First time called, we'll pass through here. */
2586 //_ALLOC(the_pFile,sizeof(pFile));
2587 the_pFile = Safe_calloc(1,sizeof(pFile));
2588 the_pFile->pbHead = the_pFile->pbTail = pb;
2589 the_pFile->functions = NULL;
2593 the_pFile->pbTail->next = pb;
2594 pb->prev = the_pFile->pbTail;
2596 the_pFile->pbTail = pb;
2599 /*-----------------------------------------------------------------*/
2600 /* removepBlock - remove a pBlock from the pFile */
2601 /*-----------------------------------------------------------------*/
2602 void removepBlock(pBlock *pb)
2610 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2612 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2615 if(pbs == the_pFile->pbHead)
2616 the_pFile->pbHead = pbs->next;
2618 if (pbs == the_pFile->pbTail)
2619 the_pFile->pbTail = pbs->prev;
2622 pbs->next->prev = pbs->prev;
2625 pbs->prev->next = pbs->next;
2632 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2636 /*-----------------------------------------------------------------*/
2637 /* printpCode - write the contents of a pCode to a file */
2638 /*-----------------------------------------------------------------*/
2639 void printpCode(FILE *of, pCode *pc)
2650 fprintf(of,"warning - unable to print pCode\n");
2653 /*-----------------------------------------------------------------*/
2654 /* printpBlock - write the contents of a pBlock to a file */
2655 /*-----------------------------------------------------------------*/
2656 void printpBlock(FILE *of, pBlock *pb)
2666 for(pc = pb->pcHead; pc; pc = pc->next) {
2671 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2681 /*-----------------------------------------------------------------*/
2683 /* pCode processing */
2687 /*-----------------------------------------------------------------*/
2689 void unlinkpCode(pCode *pc)
2695 fprintf(stderr,"Unlinking: ");
2696 printpCode(stderr, pc);
2699 pc->prev->next = pc->next;
2701 pc->next->prev = pc->prev;
2704 /* RN: I believe this should be right here, but this did not
2705 * cure the bug I was hunting... */
2706 /* must keep labels -- attach to following instruction */
2707 if (isPCI(pc) && PCI(pc)->label && pc->next)
2709 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2712 pBranchAppend (pcnext->label, PCI(pc)->label);
2716 pc->prev = pc->next = NULL;
2720 /*-----------------------------------------------------------------*/
2721 /*-----------------------------------------------------------------*/
2723 static void genericDestruct(pCode *pc)
2729 /* For instructions, tell the register (if there's one used)
2730 * that it's no longer needed */
2731 regs *reg = getRegFromInstruction(pc);
2733 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2736 /* Instead of deleting the memory used by this pCode, mark
2737 * the object as bad so that if there's a pointer to this pCode
2738 * dangling around somewhere then (hopefully) when the type is
2739 * checked we'll catch it.
2744 addpCode2pBlock(pb_dead_pcodes, pc);
2751 /*-----------------------------------------------------------------*/
2752 /* Copies the pCodeInstruction flow pointer from source pCode */
2753 /*-----------------------------------------------------------------*/
2754 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2756 pCodeFlow *pcflow = 0;
2757 for (p=pcs; p; p=p->prev) {
2759 pcflow = PCI(p)->pcflow;
2763 pcflow = (pCodeFlow*)p;
2767 PCI(pcd)->pcflow = pcflow;
2770 /*-----------------------------------------------------------------*/
2771 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2772 /* into the pCode chain containing pc1 */
2773 /*-----------------------------------------------------------------*/
2774 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2780 pc2->next = pc1->next;
2782 pc1->next->prev = pc2;
2788 /* If this is an instrution type propogate the flow */
2790 CopyFlow(PCI(pc2),pc1);
2793 /*------------------------------------------------------------------*/
2794 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2795 /* into the pCode chain containing pc1 */
2796 /*------------------------------------------------------------------*/
2797 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2803 pc2->prev = pc1->prev;
2805 pc1->prev->next = pc2;
2811 /* If this is an instrution type propogate the flow */
2813 CopyFlow(PCI(pc2),pc1);
2816 /*-----------------------------------------------------------------*/
2817 /* pCodeOpCopy - copy a pcode operator */
2818 /*-----------------------------------------------------------------*/
2819 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2821 pCodeOp *pcopnew=NULL;
2826 switch(pcop->type) {
2829 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2830 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2838 case PO_GPR_REGISTER:
2840 case PO_GPR_POINTER:
2841 case PO_SFR_REGISTER:
2845 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2846 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2847 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2848 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2852 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2853 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2854 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2858 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2859 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2865 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2866 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2867 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2871 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2872 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2873 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2877 /* Here we expand the wild card into the appropriate type: */
2878 /* By recursively calling pCodeOpCopy */
2879 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2880 if(PCOW(pcop)->matched)
2881 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2884 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2885 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2886 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2893 assert ( !"unhandled pCodeOp type copied" );
2898 pcopnew->name = Safe_strdup(pcop->name);
2900 pcopnew->name = NULL;
2905 /*-----------------------------------------------------------------*/
2906 /* popCopyReg - copy a pcode operator */
2907 /*-----------------------------------------------------------------*/
2908 pCodeOp *popCopyReg(pCodeOpReg *pc)
2912 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2913 pcor->pcop.type = pc->pcop.type;
2915 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2916 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2918 pcor->pcop.name = NULL;
2920 if (pcor->pcop.type == PO_IMMEDIATE){
2921 PCOL(pcor)->lit = PCOL(pc)->lit;
2924 pcor->rIdx = pc->rIdx;
2928 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2933 /*-----------------------------------------------------------------*/
2934 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2935 /*-----------------------------------------------------------------*/
2936 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2938 pCodeInstruction *new_pci;
2941 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2943 new_pci = PCI(newpCode(pci->op,pci->pcop));
2945 new_pci->pc.pb = pci->pc.pb;
2946 new_pci->from = pci->from;
2947 new_pci->to = pci->to;
2948 new_pci->label = pci->label;
2949 new_pci->pcflow = pci->pcflow;
2951 return PCODE(new_pci);
2954 /*-----------------------------------------------------------------*/
2955 /*-----------------------------------------------------------------*/
2956 void pCodeDeleteChain(pCode *f,pCode *t)
2961 DFPRINTF((stderr,"delete pCode:\n"));
2963 //f->print(stderr,f);
2964 //f->delete(f); this dumps core...
2969 /*-----------------------------------------------------------------*/
2970 /*-----------------------------------------------------------------*/
2971 void pBlockRegs(FILE *of, pBlock *pb)
2976 r = setFirstItem(pb->tregisters);
2978 r = setNextItem(pb->tregisters);
2983 /*-----------------------------------------------------------------*/
2984 /*-----------------------------------------------------------------*/
2985 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2990 int use_buffer = 1; // copy the string to the passed buffer pointer
2995 use_buffer = 0; // Don't bother copying the string to the buffer.
2999 switch(pcop->type) {
3003 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3006 //return PCOR(pcop)->r->name;
3010 if (PCOR(pcop)->r->type == REG_STK)
3011 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3013 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3016 SAFE_snprintf(&buffer,&size,"%s",r->name);
3025 if(PCOI(pcop)->_const) {
3027 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3028 switch(PCOI(pcop)->offset) {
3030 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3033 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3036 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3037 assert ( !"offset too large" );
3038 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3041 8 * PCOI(pcop)->offset );
3044 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3046 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3047 SAFE_snprintf(&s,&size,"(%s + %d)",
3051 switch(PCOI(pcop)->offset) {
3053 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3056 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3059 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3060 assert ( !"offset too large" );
3061 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3071 //size = sizeof(buffer);
3072 if( PCOR(pcop)->instance) {
3073 SAFE_snprintf(&s,&size,"(%s + %d)",
3075 PCOR(pcop)->instance );
3076 //fprintf(stderr,"PO_DIR %s\n",buffer);
3078 SAFE_snprintf(&s,&size,"%s",pcop->name);
3084 if(PCOLAB(pcop)->offset == 1)
3085 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3087 SAFE_snprintf(&s,&size,"%s",pcop->name);
3094 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3097 return PCOR(pcop)->r->name;
3100 /* fall through to the default case */
3104 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3112 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3113 __FILE__, __LINE__, __FUNCTION__,
3116 return "NO operand";
3120 /*-----------------------------------------------------------------*/
3121 /*-----------------------------------------------------------------*/
3122 static char *get_op_from_instruction( pCodeInstruction *pcc)
3126 return get_op(pcc->pcop,NULL,0);
3128 return ("ERROR Null: get_op_from_instruction");
3132 /*-----------------------------------------------------------------*/
3133 /*-----------------------------------------------------------------*/
3134 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3136 fprintf(of,"pcodeopprint- not implemented\n");
3139 /*-----------------------------------------------------------------*/
3140 /* pCode2str - convert a pCode instruction to string */
3141 /*-----------------------------------------------------------------*/
3142 char *pCode2str(char *str, size_t size, pCode *pc)
3150 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3152 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3154 if(PCI(pc)->isBitInst) {
3155 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3156 char *name = PCI(pc)->pcop->name;
3158 name = PCOR(PCI(pc)->pcop)->r->name;
3159 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3160 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3162 SAFE_snprintf(&s,&size,"%s,%d", name,
3163 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3164 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3165 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3167 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3168 //PCI(pc)->pcop->t.bit );
3170 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3171 if( PCI(pc)->num_ops == 2)
3172 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3174 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3176 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3177 if( PCI(pc)->num_ops == 2)
3178 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3185 /* assuming that comment ends with a \n */
3186 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3190 /* assuming that inline code ends with a \n */
3191 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3195 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3198 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3201 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3204 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3207 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3208 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);
3211 if(PCAD(pc)->directive) {
3212 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3213 } else if(PCAD(pc)->arg) {
3214 /* special case to handle inline labels without a tab */
3215 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3220 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3226 /*-----------------------------------------------------------------*/
3227 /* genericPrint - the contents of a pCode to a file */
3228 /*-----------------------------------------------------------------*/
3229 static void genericPrint(FILE *of, pCode *pc)
3236 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3240 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3244 // If the opcode has a label, print that first
3247 pCodeInstruction *pci = PCI(pc);
3248 pBranch *pbl = pci->label;
3249 while(pbl && pbl->pc) {
3250 if(pbl->pc->type == PC_LABEL)
3251 pCodePrintLabel(of, pbl->pc);
3256 genericPrint(of,PCODE(pci->cline));
3259 pCode2str(str, 256, pc);
3261 fprintf(of,"%s",str);
3265 pCodeOpReg *pcor = PCOR(pci->pcop);
3266 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3268 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3269 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3270 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3275 pBranch *dpb = pc->to; // debug
3277 switch ( dpb->pc->type) {
3279 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3282 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3285 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3288 fprintf(of, "\t;flow");
3302 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3303 if(PCW(pc)->pci.label)
3304 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3306 if(PCW(pc)->operand) {
3307 fprintf(of,";\toperand ");
3308 pCodeOpPrint(of,PCW(pc)->operand );
3314 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3315 if(PCFL(pc)->ancestor)
3316 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3318 fprintf(of,"; from: ");
3320 pCodeFlowLink *link;
3321 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3323 fprintf(of,"%03x ",link->pcflow->pc.seq);
3326 fprintf(of,"; to: ");
3328 pCodeFlowLink *link;
3329 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3331 fprintf(of,"%03x ",link->pcflow->pc.seq);
3339 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3340 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3345 pBranch *pbl = PCAD(pc)->pci.label;
3346 while(pbl && pbl->pc) {
3347 if(pbl->pc->type == PC_LABEL)
3348 pCodePrintLabel(of, pbl->pc);
3352 if(PCAD(pc)->directive) {
3353 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3356 /* special case to handle inline labels without tab */
3357 fprintf(of, "%s\n", PCAD(pc)->arg);
3363 fprintf(of,"unknown pCode type %d\n",pc->type);
3367 /*-----------------------------------------------------------------*/
3368 /* pCodePrintFunction - prints function begin/end */
3369 /*-----------------------------------------------------------------*/
3371 static void pCodePrintFunction(FILE *of, pCode *pc)
3377 if( ((pCodeFunction *)pc)->modname)
3378 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3380 if(PCF(pc)->fname) {
3381 pBranch *exits = PCF(pc)->to;
3383 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3386 exits = exits->next;
3389 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3392 if((PCF(pc)->from &&
3393 PCF(pc)->from->pc->type == PC_FUNCTION &&
3394 PCF(PCF(pc)->from->pc)->fname) )
3395 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3397 fprintf(of,"; exit point [can't find entry point]\n");
3400 /*-----------------------------------------------------------------*/
3401 /* pCodePrintLabel - prints label */
3402 /*-----------------------------------------------------------------*/
3404 static void pCodePrintLabel(FILE *of, pCode *pc)
3411 fprintf(of,"%s\n",PCL(pc)->label);
3412 else if (PCL(pc)->key >=0)
3413 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3415 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3419 /*-----------------------------------------------------------------*/
3420 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3421 /* remove it if it is found. */
3422 /*-----------------------------------------------------------------*/
3423 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3429 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3430 b = PCI(pcl)->label;
3432 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3436 //fprintf (stderr, "%s \n",__FUNCTION__);
3437 //pcl->print(stderr,pcl);
3438 //pc->print(stderr,pc);
3441 //fprintf (stderr, "found label\n");
3445 bprev->next = b->next; /* Not first pCode in chain */
3449 PCI(pcl)->label = b->next; /* First pCode in chain */
3452 return; /* A label can't occur more than once */
3459 /*-----------------------------------------------------------------*/
3460 /*-----------------------------------------------------------------*/
3461 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3480 /*-----------------------------------------------------------------*/
3481 /* pBranchLink - given two pcodes, this function will link them */
3482 /* together through their pBranches */
3483 /*-----------------------------------------------------------------*/
3484 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3488 // Declare a new branch object for the 'from' pCode.
3490 //_ALLOC(b,sizeof(pBranch));
3491 b = Safe_calloc(1,sizeof(pBranch));
3492 b->pc = PCODE(t); // The link to the 'to' pCode.
3495 f->to = pBranchAppend(f->to,b);
3497 // Now do the same for the 'to' pCode.
3499 //_ALLOC(b,sizeof(pBranch));
3500 b = Safe_calloc(1,sizeof(pBranch));
3504 t->from = pBranchAppend(t->from,b);
3509 /*-----------------------------------------------------------------*/
3510 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3512 /*-----------------------------------------------------------------*/
3513 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3526 /*-----------------------------------------------------------------*/
3527 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3528 /*-----------------------------------------------------------------*/
3529 static void pCodeUnlink(pCode *pc)
3534 if(!pc->prev || !pc->next) {
3535 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3539 /* first remove the pCode from the chain */
3540 pc->prev->next = pc->next;
3541 pc->next->prev = pc->prev;
3543 /* Now for the hard part... */
3545 /* Remove the branches */
3549 pc1 = pb1->pc; /* Get the pCode that branches to the
3550 * one we're unlinking */
3552 /* search for the link back to this pCode (the one we're
3554 if(pb2 = pBranchFind(pc1->to,pc)) {
3555 pb2->pc = pc->to->pc; // make the replacement
3557 /* if the pCode we're unlinking contains multiple 'to'
3558 * branches (e.g. this a skip instruction) then we need
3559 * to copy these extra branches to the chain. */
3561 pBranchAppend(pb2, pc->to->next);
3570 /*-----------------------------------------------------------------*/
3571 /*-----------------------------------------------------------------*/
3573 static void genericAnalyze(pCode *pc)
3583 // Go through the pCodes that are in pCode chain and link
3584 // them together through the pBranches. Note, the pCodes
3585 // are linked together as a contiguous stream like the
3586 // assembly source code lines. The linking here mimics this
3587 // except that comments are not linked in.
3589 pCode *npc = pc->next;
3591 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3592 pBranchLink(pc,npc);
3597 /* reached the end of the pcode chain without finding
3598 * an instruction we could link to. */
3602 fprintf(stderr,"analyze PC_FLOW\n");
3606 fprintf(stderr,";A bad pCode is being used\n");
3612 /*-----------------------------------------------------------------*/
3613 /*-----------------------------------------------------------------*/
3614 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3618 if(pc->type == PC_LABEL) {
3619 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3622 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3623 pbr = PCI(pc)->label;
3625 if(pbr->pc->type == PC_LABEL) {
3626 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3636 /*-----------------------------------------------------------------*/
3637 /*-----------------------------------------------------------------*/
3638 int checkLabel(pCode *pc)
3642 if(pc && isPCI(pc)) {
3643 pbr = PCI(pc)->label;
3645 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3655 /*-----------------------------------------------------------------*/
3656 /* findLabelinpBlock - Search the pCode for a particular label */
3657 /*-----------------------------------------------------------------*/
3658 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3665 for(pc = pb->pcHead; pc; pc = pc->next)
3666 if(compareLabel(pc,pcop_label))
3672 /*-----------------------------------------------------------------*/
3673 /* findLabel - Search the pCode for a particular label */
3674 /*-----------------------------------------------------------------*/
3675 pCode * findLabel(pCodeOpLabel *pcop_label)
3683 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3684 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3688 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3692 /*-----------------------------------------------------------------*/
3693 /* findNextpCode - given a pCode, find the next of type 'pct' */
3694 /* in the linked list */
3695 /*-----------------------------------------------------------------*/
3696 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3709 /*-----------------------------------------------------------------*/
3710 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3711 /* in the linked list */
3712 /*-----------------------------------------------------------------*/
3713 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3717 if(pc->type == pct) {
3719 static unsigned int stop;
3721 stop++; // Place break point here
3732 /*-----------------------------------------------------------------*/
3733 /* findNextInstruction - given a pCode, find the next instruction */
3734 /* in the linked list */
3735 /*-----------------------------------------------------------------*/
3736 pCode * findNextInstruction(pCode *pci)
3741 if((pc->type == PC_OPCODE)
3742 || (pc->type == PC_WILD)
3743 || (pc->type == PC_ASMDIR))
3747 fprintf(stderr,"findNextInstruction: ");
3748 printpCode(stderr, pc);
3753 //fprintf(stderr,"Couldn't find instruction\n");
3757 /*-----------------------------------------------------------------*/
3758 /* findNextInstruction - given a pCode, find the next instruction */
3759 /* in the linked list */
3760 /*-----------------------------------------------------------------*/
3761 pCode * findPrevInstruction(pCode *pci)
3767 if((pc->type == PC_OPCODE)
3768 || (pc->type == PC_WILD)
3769 || (pc->type == PC_ASMDIR))
3774 fprintf(stderr,"pic16_findPrevInstruction: ");
3775 printpCode(stderr, pc);
3780 //fprintf(stderr,"Couldn't find instruction\n");
3784 /*-----------------------------------------------------------------*/
3785 /* findFunctionEnd - given a pCode find the end of the function */
3786 /* that contains it */
3787 /*-----------------------------------------------------------------*/
3788 pCode * findFunctionEnd(pCode *pc)
3791 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3797 fprintf(stderr,"Couldn't find function end\n");
3802 /*-----------------------------------------------------------------*/
3803 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3804 /* instruction with which it is associated. */
3805 /*-----------------------------------------------------------------*/
3806 static void AnalyzeLabel(pCode *pc)
3815 static void AnalyzeGOTO(pCode *pc)
3818 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3822 static void AnalyzeSKIP(pCode *pc)
3825 pBranchLink(pc,findNextInstruction(pc->next));
3826 pBranchLink(pc,findNextInstruction(pc->next->next));
3830 static void AnalyzeRETURN(pCode *pc)
3833 // branch_link(pc,findFunctionEnd(pc->next));
3839 /*-----------------------------------------------------------------*/
3840 /*-----------------------------------------------------------------*/
3841 regs * getRegFromInstruction(pCode *pc)
3847 PCI(pc)->num_ops == 0 )
3850 switch(PCI(pc)->pcop->type) {
3857 case PO_SFR_REGISTER:
3860 return PCOR(PCI(pc)->pcop)->r;
3862 case PO_GPR_REGISTER:
3865 r = PCOR(PCI(pc)->pcop)->r;
3868 return dirregWithName(PCI(pc)->pcop->name);
3874 r = PCOI(PCI(pc)->pcop)->r;
3877 return dirregWithName(PCI(pc)->pcop->name);
3887 /*-----------------------------------------------------------------*/
3888 /*-----------------------------------------------------------------*/
3890 void AnalyzepBlock(pBlock *pb)
3897 /* Find all of the registers used in this pBlock
3898 * by looking at each instruction and examining it's
3901 for(pc = pb->pcHead; pc; pc = pc->next) {
3903 /* Is this an instruction with operands? */
3904 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3906 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3907 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3909 /* Loop through all of the registers declared so far in
3910 this block and see if we find this one there */
3912 regs *r = setFirstItem(pb->tregisters);
3915 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3916 PCOR(PCI(pc)->pcop)->r = r;
3919 r = setNextItem(pb->tregisters);
3923 /* register wasn't found */
3924 //r = Safe_calloc(1, sizeof(regs));
3925 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3926 //addSet(&pb->tregisters, r);
3927 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3928 //PCOR(PCI(pc)->pcop)->r = r;
3929 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3931 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3934 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3935 if(PCOR(PCI(pc)->pcop)->r) {
3936 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3937 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3939 if(PCI(pc)->pcop->name)
3940 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3942 fprintf(stderr,"ERROR: NULL register\n");
3951 /*-----------------------------------------------------------------*/
3953 /*-----------------------------------------------------------------*/
3954 void InsertpFlow(pCode *pc, pCode **pflow)
3957 PCFL(*pflow)->end = pc;
3959 if(!pc || !pc->next)
3962 *pflow = newpCodeFlow();
3963 pCodeInsertAfter(pc, *pflow);
3966 /*-----------------------------------------------------------------*/
3967 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3968 /* the flow blocks. */
3970 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3971 * point the instruction flow changes.
3973 /*-----------------------------------------------------------------*/
3974 void BuildFlow(pBlock *pb)
3977 pCode *last_pci=NULL;
3984 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3985 /* Insert a pCodeFlow object at the beginning of a pBlock */
3987 InsertpFlow(pb->pcHead, &pflow);
3989 //pflow = newpCodeFlow(); /* Create a new Flow object */
3990 //pflow->next = pb->pcHead; /* Make the current head the next object */
3991 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3992 //pb->pcHead = pflow; /* Make the Flow object the head */
3995 for( pc = findNextInstruction(pb->pcHead);
3997 pc=findNextInstruction(pc)) {
4000 PCI(pc)->pcflow = PCFL(pflow);
4002 //fprintf(stderr," build: ");
4003 //pc->print(stderr, pc);
4004 //pflow->print(stderr,pflow);
4006 if (checkLabel(pc)) {
4008 /* This instruction marks the beginning of a
4009 * new flow segment */
4014 /* If the previous pCode is not a flow object, then
4015 * insert a new flow object. (This check prevents
4016 * two consecutive flow objects from being insert in
4017 * the case where a skip instruction preceeds an
4018 * instruction containing a label.) */
4020 last_pci = findPrevInstruction (pc->prev);
4022 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4023 InsertpFlow(last_pci, &pflow);
4025 PCI(pc)->pcflow = PCFL(pflow);
4029 if(isPCI_SKIP(pc)) {
4031 /* The two instructions immediately following this one
4032 * mark the beginning of a new flow segment */
4034 while(pc && isPCI_SKIP(pc)) {
4036 PCI(pc)->pcflow = PCFL(pflow);
4040 InsertpFlow(pc, &pflow);
4041 pc=findNextInstruction(pc->next);
4049 PCI(pc)->pcflow = PCFL(pflow);
4051 InsertpFlow(pc, &pflow);
4053 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4055 InsertpFlow(pc, &pflow);
4064 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4066 PCFL(pflow)->end = pb->pcTail;
4069 /*-------------------------------------------------------------------*/
4070 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4071 /* the flow blocks. */
4073 * unBuildFlow removes pCodeFlow objects from a pCode chain
4075 /*-----------------------------------------------------------------*/
4076 void unBuildFlow(pBlock *pb)
4091 if(PCI(pc)->pcflow) {
4092 //free(PCI(pc)->pcflow);
4093 PCI(pc)->pcflow = NULL;
4096 } else if(isPCFL(pc) )
4105 /*-----------------------------------------------------------------*/
4106 /*-----------------------------------------------------------------*/
4107 void dumpCond(int cond)
4110 static char *pcc_str[] = {
4124 int ncond = sizeof(pcc_str) / sizeof(char *);
4127 fprintf(stderr, "0x%04X\n",cond);
4129 for(i=0,j=1; i<ncond; i++, j<<=1)
4131 fprintf(stderr, " %s\n",pcc_str[i]);
4135 /*-----------------------------------------------------------------*/
4136 /*-----------------------------------------------------------------*/
4137 void FlowStats(pCodeFlow *pcflow)
4145 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4147 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4150 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4155 fprintf(stderr, " FlowStats inCond: ");
4156 dumpCond(pcflow->inCond);
4157 fprintf(stderr, " FlowStats outCond: ");
4158 dumpCond(pcflow->outCond);
4162 /*-----------------------------------------------------------------*
4163 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4164 * if it affects the banking bits.
4166 * return: -1 == Banking bits are unaffected by this pCode.
4168 * return: > 0 == Banking bits are affected.
4170 * If the banking bits are affected, then the returned value describes
4171 * which bits are affected and how they're affected. The lower half
4172 * of the integer maps to the bits that are affected, the upper half
4173 * to whether they're set or cleared.
4175 *-----------------------------------------------------------------*/
4177 #define SET_BANK_BIT (1 << 16)
4178 #define CLR_BANK_BIT 0
4180 static int isBankInstruction(pCode *pc)
4188 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4190 // Check to see if the register banks are changing
4191 if(PCI(pc)->isModReg) {
4193 pCodeOp *pcop = PCI(pc)->pcop;
4194 switch(PCI(pc)->op) {
4197 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4198 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4199 return SET_BANK_BIT | PIC_RP0_BIT;
4202 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4203 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4204 return CLR_BANK_BIT | PIC_RP0_BIT;
4209 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4210 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4211 return CLR_BANK_BIT | PIC_RP1_BIT;
4213 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4214 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4215 return CLR_BANK_BIT | PIC_RP1_BIT;
4219 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4220 //genericPrint(stderr, pc);
4231 /*-----------------------------------------------------------------*/
4232 /*-----------------------------------------------------------------*/
4234 static void FillFlow(pCodeFlow *pcflow)
4242 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4244 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4247 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4254 isBankInstruction(pc);
4256 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4259 fprintf(stderr, " FillFlow - Bad end of flow\n");
4261 fprintf(stderr, " FillFlow - Ending flow with\n ");
4262 pc->print(stderr,pc);
4265 fprintf(stderr, " FillFlow inCond: ");
4266 dumpCond(pcflow->inCond);
4267 fprintf(stderr, " FillFlow outCond: ");
4268 dumpCond(pcflow->outCond);
4273 /*-----------------------------------------------------------------*/
4274 /*-----------------------------------------------------------------*/
4275 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4277 pCodeFlowLink *fromLink, *toLink;
4279 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4280 if (from) from->pc.print(stderr, &from->pc);
4281 else fprintf(stderr, "(null)");
4282 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4283 from && from->pcflow ? from->pcflow->pc.seq : 0,
4284 to && to->pcflow ? to->pcflow->pc.seq : 0);
4285 if (to) to->pc.print(stderr, &to->pc);
4286 else fprintf(stderr, "(null)");
4289 if(!from || !to || !to->pcflow || !from->pcflow)
4292 fromLink = newpCodeFlowLink(from->pcflow);
4293 toLink = newpCodeFlowLink(to->pcflow);
4295 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4296 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4300 /*-----------------------------------------------------------------*
4301 * void LinkFlow(pBlock *pb)
4303 * In BuildFlow, the PIC code has been partitioned into contiguous
4304 * non-branching segments. In LinkFlow, we determine the execution
4305 * order of these segments. For example, if one of the segments ends
4306 * with a skip, then we know that there are two possible flow segments
4307 * to which control may be passed.
4308 *-----------------------------------------------------------------*/
4309 void LinkFlow(pBlock *pb)
4315 //fprintf(stderr,"linkflow \n");
4317 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4319 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4322 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4324 //fprintf(stderr," link: ");
4325 //pcflow->print(stderr,pcflow);
4327 //FillFlow(PCFL(pcflow));
4329 /* find last instruction in flow */
4330 pc = findPrevInstruction (PCFL(pcflow)->end);
4332 fprintf(stderr, "%s: flow without end (%u)?\n",
4333 __FUNCTION__, pcflow->seq );
4337 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4338 //pc->print(stderr, pc);
4339 if(isPCI_SKIP(pc)) {
4340 //fprintf(stderr, "ends with skip\n");
4341 //pc->print(stderr,pc);
4342 pct=findNextInstruction(pc->next);
4343 LinkFlow_pCode(PCI(pc),PCI(pct));
4344 pct=findNextInstruction(pct->next);
4345 LinkFlow_pCode(PCI(pc),PCI(pct));
4349 if(isPCI_BRANCH(pc)) {
4350 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4352 //fprintf(stderr, "ends with branch\n ");
4353 //pc->print(stderr,pc);
4355 if(!(pcol && isPCOLAB(pcol))) {
4356 if((PCI(pc)->op != POC_RETLW)
4357 && (PCI(pc)->op != POC_RETURN)
4358 && (PCI(pc)->op != POC_CALL)
4359 && (PCI(pc)->op != POC_RETFIE) )
4361 pc->print(stderr,pc);
4362 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4366 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4367 LinkFlow_pCode(PCI(pc),PCI(pct));
4369 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4370 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4371 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4373 /* link CALLs to next instruction */
4374 if (PCI(pc)->op != POC_CALL) continue;
4378 //fprintf(stderr, "ends with non-branching instruction:\n");
4379 //pc->print(stderr,pc);
4381 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4387 //fprintf(stderr, "ends with unknown\n");
4388 //pc->print(stderr,pc);
4392 fprintf(stderr, "ends with nothing: ERROR\n");
4396 /*-----------------------------------------------------------------*/
4397 /*-----------------------------------------------------------------*/
4399 /*-----------------------------------------------------------------*/
4400 /*-----------------------------------------------------------------*/
4401 int isPCinFlow(pCode *pc, pCode *pcflow)
4407 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4410 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4416 /*-----------------------------------------------------------------*/
4417 /*-----------------------------------------------------------------*/
4419 static void BanksUsedFlow2(pCode *pcflow)
4428 if(!isPCFL(pcflow)) {
4429 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4433 pc = findNextInstruction(pcflow->next);
4435 PCFL(pcflow)->lastBank = -1;
4437 while(isPCinFlow(pc,pcflow)) {
4439 int bank_selected = isBankInstruction(pc);
4441 //if(PCI(pc)->pcflow)
4442 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4444 if(bank_selected > 0) {
4445 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4447 // This instruction is modifying banking bits before accessing registers
4449 PCFL(pcflow)->firstBank = -1;
4451 if(PCFL(pcflow)->lastBank == -1)
4452 PCFL(pcflow)->lastBank = 0;
4454 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4455 if(bank_selected & SET_BANK_BIT)
4456 PCFL(pcflow)->lastBank |= bank;
4460 reg = getRegFromInstruction(pc);
4462 if(reg && !isREGinBank(reg, bank)) {
4463 int allbanks = REGallBanks(reg);
4465 PCFL(pcflow)->firstBank = allbanks;
4467 PCFL(pcflow)->lastBank = allbanks;
4474 pc = findNextInstruction(pc->next);
4477 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4478 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4481 /*-----------------------------------------------------------------*/
4482 /*-----------------------------------------------------------------*/
4484 static void BanksUsedFlow(pBlock *pb)
4489 //pb->pcHead->print(stderr, pb->pcHead);
4491 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4492 //pcflow->print(stderr,pcflow);
4494 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4496 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4498 BanksUsedFlow2(pcflow);
4504 void pCodeReplace (pCode *old, pCode *new)
4506 pCodeInsertAfter (old, new);
4508 /* special handling for pCodeInstructions */
4509 if (isPCI(new) && isPCI(old))
4511 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4512 PCI(new)->from = PCI(old)->from;
4513 PCI(new)->to = PCI(old)->to;
4514 PCI(new)->label = PCI(old)->label;
4515 PCI(new)->pcflow = PCI(old)->pcflow;
4516 PCI(new)->cline = PCI(old)->cline;
4519 old->destruct (old);
4522 /*-----------------------------------------------------------------*/
4523 /*-----------------------------------------------------------------*/
4524 void addpCodeComment(pCode *pc, const char *fmt, ...)
4531 if (options.verbose || debug_verbose) {
4534 vsprintf(&buffer[2], fmt, ap);
4536 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4537 pCodeInsertAfter(pc, newpc);
4542 void pBlockMergeLabels(pBlock *pb);
4543 /*-----------------------------------------------------------------*/
4544 /* Inserts a new pCodeInstruction before an existing one */
4545 /*-----------------------------------------------------------------*/
4546 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4550 pcprev = findPrevInstruction(pci->pc.prev);
4552 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4554 /* Move the label, if there is one */
4557 new_pci->label = pci->label;
4561 /* Move the C code comment, if there is one */
4564 new_pci->cline = pci->cline;
4568 /* The new instruction has the same pcflow block */
4569 new_pci->pcflow = pci->pcflow;
4571 /* Arrrrg: is pci's previous instruction is a skip, we need to
4572 * change that into a jump (over pci and the new instruction) ... */
4573 if (pcprev && isPCI_SKIP(pcprev))
4575 symbol *lbl = newiTempLabel (NULL);
4576 pCode *label = newpCodeLabel (NULL, lbl->key);
4577 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4579 pCodeInsertAfter (pcprev, jump);
4581 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4582 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4583 switch (PCI(pcprev)->op) {
4588 // These are turned into non-skipping instructions, so
4589 // insert 'BTFSC STATUS, Z' after pcprev
4590 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4593 // no special actions required
4596 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4598 pCodeInsertAfter((pCode*)pci, label);
4599 pBlockMergeLabels(pci->pc.pb);
4603 /*-----------------------------------------------------------------*/
4604 /*-----------------------------------------------------------------*/
4605 static void insertBankSel(pCodeInstruction *pci, const char *name)
4611 // This is a NOP for single-banked devices.
4612 if (pic14_getMaxRam() < 0x80) return;
4613 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4614 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4616 pcop = popCopyReg(PCOR(pci->pcop));
4617 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4618 if (pcop->name == 0)
4619 pcop->name = strdup(name);
4620 new_pc = newpCode(POC_BANKSEL, pcop);
4622 insertPCodeInstruction(pci, PCI(new_pc));
4625 /*-----------------------------------------------------------------*/
4626 /*-----------------------------------------------------------------*/
4627 static int sameBank(regs *reg, const char *new_bank, const char *cur_bank)
4629 if (!cur_bank) return 0;
4631 // identify '(regname + X)' and 'regname'
4632 if (reg && reg->name && reg->name[0] == '(' && !strncmp(®->name[1], cur_bank, strlen(cur_bank))) return 1;
4633 if (new_bank && new_bank[0] == '(' && !strncmp(&new_bank[1], cur_bank, strlen(cur_bank))) return 1;
4634 if (cur_bank[0] == '(' && reg && reg->name && !strncmp(reg->name, &cur_bank[1], strlen(reg->name))) return 1;
4635 if (cur_bank[0] == '(' && new_bank && !strncmp(new_bank, &cur_bank[1], strlen(new_bank))) return 1;
4637 // XXX: identify '(regname + X)' and '(regname + Y)'
4639 return ((reg && reg->name && !strcmp(reg->name, cur_bank)) || (new_bank && !strcmp(new_bank, cur_bank)));
4642 /*-----------------------------------------------------------------*/
4643 /*-----------------------------------------------------------------*/
4644 void FixRegisterBanking(pBlock *pb)
4647 pCodeInstruction *pci;
4649 const char *cur_bank, *new_bank;
4650 unsigned cur_mask, new_mask, max_mask;
4654 max_mask = pic14_getPIC()->bankMask;
4655 cur_mask = max_mask;
4658 for (pc = pb->pcHead; pc; pc = pc->next)
4660 // this one has a label---might check bank at all jumps here...
4661 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4662 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4663 cur_bank = NULL; // start new flow
4664 cur_mask = max_mask;
4667 // this one is/might be a label or BANKSEL---assume nothing
4668 if (isPCL(pc) || isPCASMDIR(pc)) {
4669 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4671 cur_mask = max_mask;
4674 // this one modifies STATUS
4675 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4679 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4680 // might need a BANKSEL
4681 reg = getRegFromInstruction(pc);
4684 new_bank = reg->name;
4685 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4686 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4687 new_mask = reg->alias;
4688 } else if (pci->pcop && pci->pcop->name) {
4689 new_bank = pci->pcop->name;
4690 new_mask = 0; // unknown, assume worst case
4692 assert(!"Could not get register from instruction.");
4696 // XXX: add switch to disable these
4698 // reg present in all banks possibly selected?
4699 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4700 // no BANKSEL required
4701 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4705 cur_mask &= new_mask;
4707 if (sameBank(reg, new_bank, cur_bank)) {
4708 // no BANKSEL required
4709 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4714 cur_mask = new_mask;
4715 cur_bank = new_bank;
4716 insertBankSel(pci, cur_bank);
4722 /*-----------------------------------------------------------------*/
4723 /*-----------------------------------------------------------------*/
4724 int OptimizepBlock(pBlock *pb)
4729 if(!pb || options.nopeep)
4732 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4734 for(pc = pb->pcHead; pc; pc = pc->next)
4735 matches += pCodePeepMatchRule(pc);
4738 pc = findNextInstruction(pb->pcHead);
4746 if(pCodePeepMatchRule(pc)) {
4751 pc = findNextInstruction(pcprev->next);
4753 pc = findNextInstruction(pb->pcHead);
4755 pc = findNextInstruction(pc->next);
4759 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4764 /*-----------------------------------------------------------------*/
4765 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4766 /*-----------------------------------------------------------------*/
4767 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4771 for(pc = pcs; pc; pc = pc->next) {
4773 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4775 (PCI(pc)->pcop->type == PO_LABEL) &&
4776 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4783 /*-----------------------------------------------------------------*/
4784 /*-----------------------------------------------------------------*/
4785 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4792 (PCI(pc)->pcop->type == PO_LABEL)) {
4794 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4796 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4798 free(pcol->pcop.name);
4800 /* If the key is negative, then we (probably) have a label to
4801 * a function and the name is already defined */
4804 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4808 //sprintf(buffer,"_%05d_DS_",pcl->key);
4810 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4812 pcol->pcop.name = Safe_strdup(s);
4813 pcol->key = pcl->key;
4814 //pc->print(stderr,pc);
4821 /*-----------------------------------------------------------------*/
4822 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4823 /* pCode chain if they're not used. */
4824 /*-----------------------------------------------------------------*/
4825 void pBlockRemoveUnusedLabels(pBlock *pb)
4827 pCode *pc; pCodeLabel *pcl;
4832 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4834 pBranch *pbr = PCI(pc)->label;
4835 if(pbr && pbr->next) {
4836 pCode *pcd = pb->pcHead;
4838 //fprintf(stderr, "multiple labels\n");
4839 //pc->print(stderr,pc);
4844 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4845 //fprintf(stderr,"Used by:\n");
4846 //pcd->print(stderr,pcd);
4848 exchangeLabels(PCL(pbr->pc),pcd);
4857 for(pc = pb->pcHead; pc; pc = pc->next) {
4859 if(isPCL(pc)) // Label pcode
4861 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4862 pcl = PCL(PCI(pc)->label->pc);
4865 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4867 /* This pCode is a label, so search the pBlock to see if anyone
4870 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4871 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4872 /* Couldn't find an instruction that refers to this label
4873 * So, unlink the pCode label from it's pCode chain
4874 * and destroy the label */
4875 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4877 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4878 if(pc->type == PC_LABEL) {
4880 pCodeLabelDestruct(pc);
4882 unlinkpCodeFromBranch(pc, PCODE(pcl));
4883 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4894 /*-----------------------------------------------------------------*/
4895 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4896 /* chain and put them into pBranches that are */
4897 /* associated with the appropriate pCode */
4899 /*-----------------------------------------------------------------*/
4900 void pBlockMergeLabels(pBlock *pb)
4903 pCode *pc, *pcnext=NULL;
4908 /* First, Try to remove any unused labels */
4909 //pBlockRemoveUnusedLabels(pb);
4911 /* Now loop through the pBlock and merge the labels with the opcodes */
4914 // for(pc = pb->pcHead; pc; pc = pc->next) {
4917 pCode *pcn = pc->next;
4919 if(pc->type == PC_LABEL) {
4921 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4922 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4923 if((pcnext = findNextInstruction(pc) )) {
4925 // Unlink the pCode label from it's pCode chain
4928 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4929 // And link it into the instruction's pBranch labels. (Note, since
4930 // it's possible to have multiple labels associated with one instruction
4931 // we must provide a means to accomodate the additional labels. Thus
4932 // the labels are placed into the singly-linked list "label" as
4933 // opposed to being a single member of the pCodeInstruction.)
4935 //_ALLOC(pbr,sizeof(pBranch));
4936 pbr = Safe_calloc(1,sizeof(pBranch));
4940 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4943 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4945 } else if(pc->type == PC_CSOURCE) {
4947 /* merge the source line symbolic info into the next instruction */
4948 if((pcnext = findNextInstruction(pc) )) {
4950 // Unlink the pCode label from it's pCode chain
4952 PCI(pcnext)->cline = PCCS(pc);
4953 //fprintf(stderr, "merging CSRC\n");
4954 //genericPrint(stderr,pcnext);
4960 pBlockRemoveUnusedLabels(pb);
4964 /*-----------------------------------------------------------------*/
4965 /*-----------------------------------------------------------------*/
4966 int OptimizepCode(char dbName)
4968 #define MAX_PASSES 4
4977 DFPRINTF((stderr," Optimizing pCode\n"));
4981 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4982 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4983 matches += OptimizepBlock(pb);
4986 while(matches && ++passes < MAX_PASSES);
4991 /*-----------------------------------------------------------------*/
4992 /* popCopyGPR2Bit - copy a pcode operator */
4993 /*-----------------------------------------------------------------*/
4995 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4999 pcop = newpCodeOpBit(pc->name, bitval, 0);
5001 if( !( (pcop->type == PO_LABEL) ||
5002 (pcop->type == PO_LITERAL) ||
5003 (pcop->type == PO_STR) ))
5004 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5009 /*-----------------------------------------------------------------*/
5010 /*-----------------------------------------------------------------*/
5011 void pBlockDestruct(pBlock *pb)
5022 /*-----------------------------------------------------------------*/
5023 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5024 /* name dbName and combine them */
5025 /* into one block */
5026 /*-----------------------------------------------------------------*/
5027 void mergepBlocks(char dbName)
5030 pBlock *pb, *pbmerged = NULL,*pbn;
5032 pb = the_pFile->pbHead;
5034 //fprintf(stderr," merging blocks named %c\n",dbName);
5038 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5039 if( getpBlock_dbName(pb) == dbName) {
5041 //fprintf(stderr," merged block %c\n",dbName);
5046 addpCode2pBlock(pbmerged, pb->pcHead);
5047 /* addpCode2pBlock doesn't handle the tail: */
5048 pbmerged->pcTail = pb->pcTail;
5050 pb->prev->next = pbn;
5052 pbn->prev = pb->prev;
5057 //printpBlock(stderr, pbmerged);
5064 /*-----------------------------------------------------------------*/
5065 /* AnalyzeFlow - Examine the flow of the code and optimize */
5067 /* level 0 == minimal optimization */
5068 /* optimize registers that are used only by two instructions */
5069 /* level 1 == maximal optimization */
5070 /* optimize by looking at pairs of instructions that use the */
5072 /*-----------------------------------------------------------------*/
5074 void AnalyzeFlow(int level)
5076 static int times_called=0;
5084 /* if this is not the first time this function has been called,
5085 then clean up old flow information */
5086 if(times_called++) {
5087 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5090 RegsUnMapLiveRanges();
5096 /* Phase 2 - Flow Analysis - Register Banking
5098 * In this phase, the individual flow blocks are examined
5099 * and register banking is fixed.
5102 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5103 //FixRegisterBanking(pb);
5105 /* Phase 2 - Flow Analysis
5107 * In this phase, the pCode is partition into pCodeFlow
5108 * blocks. The flow blocks mark the points where a continuous
5109 * stream of instructions changes flow (e.g. because of
5110 * a call or goto or whatever).
5113 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5117 /* Phase 2 - Flow Analysis - linking flow blocks
5119 * In this phase, the individual flow blocks are examined
5120 * to determine their order of excution.
5123 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5126 /* Phase 3 - Flow Analysis - Flow Tree
5128 * In this phase, the individual flow blocks are examined
5129 * to determine their order of excution.
5132 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5136 /* Phase x - Flow Analysis - Used Banks
5138 * In this phase, the individual flow blocks are examined
5139 * to determine the Register Banks they use
5142 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5146 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5147 pCodeRegMapLiveRanges(pb);
5149 RemoveUnusedRegisters();
5151 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5152 pCodeRegOptimizeRegUsage(level);
5157 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5162 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5164 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5165 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5166 pcflow = pcflow->next) {
5168 FillFlow(PCFL(pcflow));
5173 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5175 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5176 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5177 pcflow = pcflow->next) {
5179 FlowStats(PCFL(pcflow));
5185 /*-----------------------------------------------------------------*/
5186 /* AnalyzeBanking - Called after the memory addresses have been */
5187 /* assigned to the registers. */
5189 /*-----------------------------------------------------------------*/
5191 void AnalyzeBanking(void)
5195 if(!picIsInitialized()) {
5196 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5200 if (!the_pFile) return;
5202 /* Phase x - Flow Analysis - Used Banks
5204 * In this phase, the individual flow blocks are examined
5205 * to determine the Register Banks they use
5211 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5212 // BanksUsedFlow(pb);
5213 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5214 FixRegisterBanking(pb);
5221 /*-----------------------------------------------------------------*/
5222 /*-----------------------------------------------------------------*/
5223 DEFSETFUNC (resetrIdx)
5225 regs *r = (regs *)item;
5233 /*-----------------------------------------------------------------*/
5234 /* InitRegReuse - Initialises variables for code analyzer */
5235 /*-----------------------------------------------------------------*/
5237 void InitReuseReg(void)
5239 /* Find end of statically allocated variables for start idx */
5240 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5241 /* XXX: Avoid clashes with fixed registers, start late. */
5242 unsigned maxIdx = 0x1000;
5244 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5245 if (r->type != REG_SFR) {
5246 maxIdx += r->size; /* Increment for all statically allocated variables */
5250 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5253 /*-----------------------------------------------------------------*/
5254 /*-----------------------------------------------------------------*/
5255 static unsigned register_reassign(pBlock *pb, unsigned idx)
5259 /* check recursion */
5260 pc = setFirstItem(pb->function_entries);
5266 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5268 if (pb->tregisters) {
5270 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5271 if (r->type == REG_GPR) {
5273 if (r->rIdx < (int)idx) {
5276 if (peakIdx < idx) peakIdx = idx;
5277 sprintf(s,"r0x%02X", r->rIdx);
5278 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5280 r->name = Safe_strdup(s);
5286 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5288 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5289 char *dest = get_op_from_instruction(PCI(pc));
5291 pCode *pcn = findFunction(dest);
5293 register_reassign(pcn->pb,idx);
5302 /*------------------------------------------------------------------*/
5303 /* ReuseReg were call tree permits */
5305 /* Re-allocate the GPR for optimum reuse for a given pblock */
5306 /* eg if a function m() calls function f1() and f2(), where f1 */
5307 /* allocates a local variable vf1 and f2 allocates a local */
5308 /* variable vf2. Then providing f1 and f2 do not call each other */
5309 /* they may share the same general purpose registers for vf1 and */
5311 /* This is done by first setting the the regs rIdx to start after */
5312 /* all the global variables, then walking through the call tree */
5313 /* renaming the registers to match their new idx and incrementng */
5314 /* it as it goes. If a function has already been called it will */
5315 /* only rename the registers if it has already used up those */
5316 /* registers ie rIdx of the function's registers is lower than the */
5317 /* current rIdx. That way the register will not be reused while */
5318 /* still being used by an eariler function call. */
5320 /* Note for this to work the functions need to be declared static. */
5322 /*------------------------------------------------------------------*/
5326 if (!the_pFile) return;
5328 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5329 /* Non static functions can be called from other modules so their registers must reassign */
5330 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5331 register_reassign(pb,peakIdx);
5335 /*-----------------------------------------------------------------*/
5336 /* buildCallTree - look at the flow and extract all of the calls */
5338 /*-----------------------------------------------------------------*/
5340 void buildCallTree(void )
5349 /* Now build the call tree.
5350 First we examine all of the pCodes for functions.
5351 Keep in mind that the function boundaries coincide
5352 with pBlock boundaries.
5354 The algorithm goes something like this:
5355 We have two nested loops. The outer loop iterates
5356 through all of the pBlocks/functions. The inner
5357 loop iterates through all of the pCodes for
5358 a given pBlock. When we begin iterating through
5359 a pBlock, the variable pc_fstart, pCode of the start
5360 of a function, is cleared. We then search for pCodes
5361 of type PC_FUNCTION. When one is encountered, we
5362 initialize pc_fstart to this and at the same time
5363 associate a new pBranch object that signifies a
5364 branch entry. If a return is found, then this signifies
5365 a function exit point. We'll link the pCodes of these
5366 returns to the matching pc_fstart.
5368 When we're done, a doubly linked list of pBranches
5369 will exist. The head of this list is stored in
5370 `the_pFile', which is the meta structure for all
5371 of the pCode. Look at the printCallTree function
5372 on how the pBranches are linked together.
5375 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5376 pCode *pc_fstart=NULL;
5377 for(pc = pb->pcHead; pc; pc = pc->next) {
5379 pCodeFunction *pcf = PCF(pc);
5382 if(STRCASECMP(pcf->fname, "_main") == 0) {
5383 //fprintf(stderr," found main \n");
5384 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5388 pbr = Safe_calloc(1,sizeof(pBranch));
5389 pbr->pc = pc_fstart = pc;
5392 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5394 // Here's a better way of doing the same:
5395 addSet(&pb->function_entries, pc);
5398 // Found an exit point in a function, e.g. return
5399 // (Note, there may be more than one return per function)
5401 pBranchLink(PCF(pc_fstart), pcf);
5403 addSet(&pb->function_exits, pc);
5405 } else if(isCALL(pc)) {
5406 addSet(&pb->function_calls,pc);
5412 /*-----------------------------------------------------------------*/
5413 /* AnalyzepCode - parse the pCode that has been generated and form */
5414 /* all of the logical connections. */
5416 /* Essentially what's done here is that the pCode flow is */
5418 /*-----------------------------------------------------------------*/
5420 void AnalyzepCode(char dbName)
5431 /* Phase 1 - Register allocation and peep hole optimization
5433 * The first part of the analysis is to determine the registers
5434 * that are used in the pCode. Once that is done, the peep rules
5435 * are applied to the code. We continue to loop until no more
5436 * peep rule optimizations are found (or until we exceed the
5437 * MAX_PASSES threshold).
5439 * When done, the required registers will be determined.
5445 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5447 /* First, merge the labels with the instructions */
5448 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5449 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5451 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5452 pBlockMergeLabels(pb);
5455 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5459 changes = OptimizepCode(dbName);
5461 } while(changes && (i++ < MAX_PASSES));
5466 /*-----------------------------------------------------------------*/
5467 /* ispCodeFunction - returns true if *pc is the pCode of a */
5469 /*-----------------------------------------------------------------*/
5470 bool ispCodeFunction(pCode *pc)
5473 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5479 /*-----------------------------------------------------------------*/
5480 /* findFunction - Search for a function by name (given the name) */
5481 /* in the set of all functions that are in a pBlock */
5482 /* (note - I expect this to change because I'm planning to limit */
5483 /* pBlock's to just one function declaration */
5484 /*-----------------------------------------------------------------*/
5485 pCode *findFunction(char *fname)
5492 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5494 pc = setFirstItem(pb->function_entries);
5497 if((pc->type == PC_FUNCTION) &&
5499 (strcmp(fname, PCF(pc)->fname)==0))
5502 pc = setNextItem(pb->function_entries);
5510 void MarkUsedRegisters(set *regset)
5515 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5516 r2 = pic14_regWithIdx(r1->rIdx);
5524 void pBlockStats(FILE *of, pBlock *pb)
5530 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5532 // for now just print the first element of each set
5533 pc = setFirstItem(pb->function_entries);
5535 fprintf(of,";entry: ");
5538 pc = setFirstItem(pb->function_exits);
5540 fprintf(of,";has an exit\n");
5544 pc = setFirstItem(pb->function_calls);
5546 fprintf(of,";functions called:\n");
5549 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5550 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5552 pc = setNextItem(pb->function_calls);
5556 r = setFirstItem(pb->tregisters);
5558 int n = elementsInSet(pb->tregisters);
5560 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5563 fprintf(of,"; %s\n",r->name);
5564 r = setNextItem(pb->tregisters);
5569 /*-----------------------------------------------------------------*/
5570 /*-----------------------------------------------------------------*/
5572 static void sequencepCode(void)
5578 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5580 pb->seq = GpCodeSequenceNumber+1;
5582 for( pc = pb->pcHead; pc; pc = pc->next)
5583 pc->seq = ++GpCodeSequenceNumber;
5589 /*-----------------------------------------------------------------*/
5590 /*-----------------------------------------------------------------*/
5592 set *register_usage(pBlock *pb)
5595 set *registers=NULL;
5596 set *registersInCallPath = NULL;
5598 / * check recursion * /
5600 pc = setFirstItem(pb->function_entries);
5607 if(pc->type != PC_FUNCTION)
5608 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5610 pc = setFirstItem(pb->function_calls);
5611 for( ; pc; pc = setNextItem(pb->function_calls)) {
5613 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5614 char *dest = get_op_from_instruction(PCI(pc));
5616 pcn = findFunction(dest);
5618 registersInCallPath = register_usage(pcn->pb);
5620 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5625 pBlockStats(stderr,pb); // debug
5628 // Mark the registers in this block as used.
5630 MarkUsedRegisters(pb->tregisters);
5631 if(registersInCallPath) {
5632 / * registers were used in the functions this pBlock has called * /
5633 / * so now, we need to see if these collide with the ones we are * /
5636 regs *r1,*r2, *newreg;
5638 DFPRINTF((stderr,"comparing registers\n"));
5640 r1 = setFirstItem(registersInCallPath);
5642 if (r1->type != REG_STK) {
5643 r2 = setFirstItem(pb->tregisters);
5645 while(r2 && (r2->type != REG_STK)) {
5647 if(r2->rIdx == r1->rIdx) {
5648 newreg = pic14_findFreeReg(REG_GPR);
5652 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5656 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5657 r1->rIdx, newreg->rIdx));
5658 r2->rIdx = newreg->rIdx;
5660 r2->name = Safe_strdup(newreg->name);
5664 newreg->wasUsed = 1;
5666 r2 = setNextItem(pb->tregisters);
5670 r1 = setNextItem(registersInCallPath);
5673 / * Collisions have been resolved. Now free the registers in the call path * /
5674 r1 = setFirstItem(registersInCallPath);
5676 newreg = pic14_regWithIdx(r1->rIdx);
5677 if (newreg) newreg->isFree = 1;
5678 r1 = setNextItem(registersInCallPath);
5682 // MarkUsedRegisters(pb->registers);
5684 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5687 DFPRINTF((stderr,"returning regs\n"));
5689 DFPRINTF((stderr,"not returning regs\n"));
5691 DFPRINTF((stderr,"pBlock after register optim.\n"));
5692 pBlockStats(stderr,pb); // debug
5699 /*-----------------------------------------------------------------*/
5700 /* printCallTree - writes the call tree to a file */
5702 /*-----------------------------------------------------------------*/
5703 void pct2(FILE *of,pBlock *pb,int indent)
5707 // set *registersInCallPath = NULL;
5713 return; //recursion ?
5715 pc = setFirstItem(pb->function_entries);
5722 for(i=0;i<indent;i++) // Indentation
5725 if(pc->type == PC_FUNCTION)
5726 fprintf(of,"%s\n",PCF(pc)->fname);
5731 pc = setFirstItem(pb->function_calls);
5732 for( ; pc; pc = setNextItem(pb->function_calls)) {
5734 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5735 char *dest = get_op_from_instruction(PCI(pc));
5737 pcn = findFunction(dest);
5739 pct2(of,pcn->pb,indent+1);
5741 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5749 /*-----------------------------------------------------------------*/
5750 /* printCallTree - writes the call tree to a file */
5752 /*-----------------------------------------------------------------*/
5754 void printCallTree(FILE *of)
5766 fprintf(of, "\npBlock statistics\n");
5767 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5772 fprintf(of,"Call Tree\n");
5773 pbr = the_pFile->functions;
5777 if(!ispCodeFunction(pc))
5778 fprintf(of,"bug in call tree");
5781 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5783 while(pc->next && !ispCodeFunction(pc->next)) {
5785 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5786 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5794 fprintf(of,"\n**************\n\na better call tree\n");
5795 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5800 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5801 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5807 /*-----------------------------------------------------------------*/
5809 /*-----------------------------------------------------------------*/
5811 void InlineFunction(pBlock *pb)
5819 pc = setFirstItem(pb->function_calls);
5821 for( ; pc; pc = setNextItem(pb->function_calls)) {
5824 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5825 pCode *pcp = pc->prev;
5831 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 */
5833 InlineFunction(pcn->pb);
5836 At this point, *pc points to a CALL mnemonic, and
5837 *pcn points to the function that is being called.
5839 To in-line this call, we need to remove the CALL
5840 and RETURN(s), and link the function pCode in with
5847 /* Check if previous instruction was a bit skip */
5848 if (isPCI_BITSKIP(pcp)) {
5850 /* Invert skip instruction and add a goto */
5851 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5853 if(isPCL(pc_call->next)) { // Label pcode
5854 pcl = PCL(pc_call->next);
5855 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5856 pcl = PCL(PCI(pc_call->next)->label->pc);
5858 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5859 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5861 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5864 /* remove callee pBlock from the pBlock linked list */
5865 removepBlock(pcn->pb);
5873 /* Remove the Function pCode */
5874 pct = findNextInstruction(pcn->next);
5876 /* Link the function with the callee */
5877 if (pcp) pcp->next = pcn->next;
5878 pcn->next->prev = pcp;
5880 /* Convert the function name into a label */
5882 pbr = Safe_calloc(1,sizeof(pBranch));
5883 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5885 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5886 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5888 /* turn all of the return's except the last into goto's */
5889 /* check case for 2 instruction pBlocks */
5890 pce = findNextInstruction(pcn->next);
5892 pCode *pce_next = findNextInstruction(pce->next);
5894 if(pce_next == NULL) {
5895 /* found the last return */
5896 pCode *pc_call_next = findNextInstruction(pc_call->next);
5898 //fprintf(stderr,"found last return\n");
5899 //pce->print(stderr,pce);
5900 pce->prev->next = pc_call->next;
5901 pc_call->next->prev = pce->prev;
5902 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5911 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5917 /*-----------------------------------------------------------------*/
5919 /*-----------------------------------------------------------------*/
5921 void InlinepCode(void)
5930 if(!functionInlining)
5933 /* Loop through all of the function definitions and count the
5934 * number of times each one is called */
5935 //fprintf(stderr,"inlining %d\n",__LINE__);
5937 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5939 pc = setFirstItem(pb->function_calls);
5941 for( ; pc; pc = setNextItem(pb->function_calls)) {
5944 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5945 if(pcn && isPCF(pcn)) {
5946 PCF(pcn)->ncalled++;
5949 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5954 //fprintf(stderr,"inlining %d\n",__LINE__);
5956 /* Now, Loop through the function definitions again, but this
5957 * time inline those functions that have only been called once. */
5959 InlineFunction(the_pFile->pbHead);
5960 //fprintf(stderr,"inlining %d\n",__LINE__);
5962 for(pb = the_pFile->pbHead; pb; pb = pb->next)