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, int shared);
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 PIC_device *init_pic(char *);
1343 void pCodeInitRegisters(void)
1345 static int initialized=0;
1346 int shareBankAddress, stkSize, haveShared;
1353 pic = init_pic(port->processor);
1354 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1355 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1356 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1357 * (used for interrupts) to fit into the shared portion of the
1359 stkSize = stkSize - 3;
1360 assert(stkSize >= 0);
1361 initStack(shareBankAddress, stkSize, haveShared);
1363 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1364 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1365 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1366 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1367 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1368 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1369 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1371 pc_status.rIdx = IDX_STATUS;
1372 pc_fsr.rIdx = IDX_FSR;
1373 pc_indf.rIdx = IDX_INDF;
1374 pc_intcon.rIdx = IDX_INTCON;
1375 pc_pcl.rIdx = IDX_PCL;
1376 pc_pclath.rIdx = IDX_PCLATH;
1378 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1379 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1380 /* Interrupt storage for status register. */
1381 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1382 /* Interrupt storage for pclath register. */
1383 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1385 pc_wsave.rIdx = pc_wsave.r->rIdx;
1386 pc_ssave.rIdx = pc_ssave.r->rIdx;
1387 pc_psave.rIdx = pc_psave.r->rIdx;
1389 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1390 pc_wsave.r->address = shareBankAddress-stkSize;
1391 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1392 pc_ssave.r->address = shareBankAddress-stkSize-1;
1393 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1394 pc_psave.r->address = shareBankAddress-stkSize-2;
1396 /* probably should put this in a separate initialization routine */
1397 pb_dead_pcodes = newpBlock();
1401 /*-----------------------------------------------------------------*/
1402 /* mnem2key - convert a pic mnemonic into a hash key */
1403 /* (BTW - this spreads the mnemonics quite well) */
1405 /*-----------------------------------------------------------------*/
1407 int mnem2key(unsigned char const *mnem)
1416 key += toupper(*mnem++) +1;
1420 return (key & 0x1f);
1424 void pic14initMnemonics(void)
1429 pCodeInstruction *pci;
1431 if(mnemonics_initialized)
1434 //FIXME - probably should NULL out the array before making the assignments
1435 //since we check the array contents below this initialization.
1437 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1438 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1439 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1440 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1441 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1442 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1443 pic14Mnemonics[POC_BCF] = &pciBCF;
1444 pic14Mnemonics[POC_BSF] = &pciBSF;
1445 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1446 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1447 pic14Mnemonics[POC_CALL] = &pciCALL;
1448 pic14Mnemonics[POC_COMF] = &pciCOMF;
1449 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1450 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1451 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1452 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1453 pic14Mnemonics[POC_DECF] = &pciDECF;
1454 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1455 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1456 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1457 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1458 pic14Mnemonics[POC_INCF] = &pciINCF;
1459 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1460 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1461 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1462 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1463 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1464 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1465 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1466 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1467 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1468 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1469 pic14Mnemonics[POC_NOP] = &pciNOP;
1470 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1471 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1472 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1473 pic14Mnemonics[POC_RLF] = &pciRLF;
1474 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1475 pic14Mnemonics[POC_RRF] = &pciRRF;
1476 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1477 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1478 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1479 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1480 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1481 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1482 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1483 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1484 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1485 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1486 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1487 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1489 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1490 if(pic14Mnemonics[i])
1491 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1492 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1495 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1496 pci = hTabNextItem(pic14MnemonicsHash, &key);
1499 mnemonics_initialized = 1;
1502 int getpCodePeepCommand(char *cmd);
1504 int getpCode(char *mnem,unsigned dest)
1507 pCodeInstruction *pci;
1508 int key = mnem2key((unsigned char *)mnem);
1510 if(!mnemonics_initialized)
1511 pic14initMnemonics();
1513 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1517 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1518 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1522 pci = hTabNextItemWK (pic14MnemonicsHash);
1529 /*-----------------------------------------------------------------*
1530 * pic14initpCodePeepCommands
1532 *-----------------------------------------------------------------*/
1533 void pic14initpCodePeepCommands(void)
1541 hTabAddItem(&pic14pCodePeepCommandsHash,
1542 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1544 } while (peepCommands[i].cmd);
1546 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1549 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1550 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1555 /*-----------------------------------------------------------------
1558 *-----------------------------------------------------------------*/
1560 int getpCodePeepCommand(char *cmd)
1564 int key = mnem2key((unsigned char *)cmd);
1567 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1570 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1571 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1575 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1582 char getpBlock_dbName(pBlock *pb)
1588 return pb->cmemmap->dbName;
1592 void pBlockConvert2ISR(pBlock *pb)
1603 /*-----------------------------------------------------------------*/
1604 /* movepBlock2Head - given the dbname of a pBlock, move all */
1605 /* instances to the front of the doubly linked */
1606 /* list of pBlocks */
1607 /*-----------------------------------------------------------------*/
1609 void movepBlock2Head(char dbName)
1616 pb = the_pFile->pbHead;
1620 if(getpBlock_dbName(pb) == dbName) {
1621 pBlock *pbn = pb->next;
1622 pb->next = the_pFile->pbHead;
1623 the_pFile->pbHead->prev = pb;
1624 the_pFile->pbHead = pb;
1627 pb->prev->next = pbn;
1629 // If the pBlock that we just moved was the last
1630 // one in the link of all of the pBlocks, then we
1631 // need to point the tail to the block just before
1632 // the one we moved.
1633 // Note: if pb->next is NULL, then pb must have
1634 // been the last pBlock in the chain.
1637 pbn->prev = pb->prev;
1639 the_pFile->pbTail = pb->prev;
1650 void copypCode(FILE *of, char dbName)
1654 if(!of || !the_pFile)
1657 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1658 if(getpBlock_dbName(pb) == dbName) {
1667 void resetpCodeStatistics (void)
1669 pcode_insns = pcode_doubles = 0;
1672 void dumppCodeStatistics (FILE *of)
1674 /* dump statistics */
1676 fprintf (of, ";\tcode size estimation:\n");
1677 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1681 void pcode_test(void)
1684 DFPRINTF((stderr,"pcode is alive!\n"));
1694 /* create the file name */
1695 strcpy(buffer,dstFileName);
1696 strcat(buffer,".p");
1698 if( !(pFile = fopen(buffer, "w" ))) {
1699 werror(E_FILE_OPEN_ERR,buffer);
1703 fprintf(pFile,"pcode dump\n\n");
1705 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1706 fprintf(pFile,"\n\tNew pBlock\n\n");
1708 fprintf(pFile,"%s",pb->cmemmap->sname);
1710 fprintf(pFile,"internal pblock");
1712 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1713 printpBlock(pFile,pb);
1717 /*-----------------------------------------------------------------*/
1718 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1719 /* ister, RegCond will return the bit being referenced. */
1721 /* fixme - why not just OR in the pcop bit field */
1722 /*-----------------------------------------------------------------*/
1724 static int RegCond(pCodeOp *pcop)
1730 if (pcop->type == PO_GPR_BIT) {
1731 char *name = pcop->name;
1733 name = PCOR(pcop)->r->name;
1734 if (strcmp(name, pc_status.pcop.name) == 0)
1736 switch(PCORB(pcop)->bit) {
1750 /*-----------------------------------------------------------------*/
1751 /* newpCode - create and return a newly initialized pCode */
1753 /* fixme - rename this */
1755 /* The purpose of this routine is to create a new Instruction */
1756 /* pCode. This is called by gen.c while the assembly code is being */
1760 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1761 /* (note that the op is analogous to but not the */
1762 /* same thing as the opcode of the instruction.) */
1763 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1766 /* a pointer to the new malloc'd pCode is returned. */
1770 /*-----------------------------------------------------------------*/
1771 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1773 pCodeInstruction *pci ;
1775 if(!mnemonics_initialized)
1776 pic14initMnemonics();
1778 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1780 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1781 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1782 pci->pc.id = PCodeID();
1785 if(pci->inCond & PCC_EXAMINE_PCOP)
1786 pci->inCond |= RegCond(pcop);
1788 if(pci->outCond & PCC_EXAMINE_PCOP)
1789 pci->outCond |= RegCond(pcop);
1791 pci->pc.prev = pci->pc.next = NULL;
1792 return (pCode *)pci;
1795 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1801 /*-----------------------------------------------------------------*/
1802 /* newpCodeWild - create a "wild" as in wild card pCode */
1804 /* Wild pcodes are used during the peep hole optimizer to serve */
1805 /* as place holders for any instruction. When a snippet of code is */
1806 /* compared to a peep hole rule, the wild card opcode will match */
1807 /* any instruction. However, the optional operand and label are */
1808 /* additional qualifiers that must also be matched before the */
1809 /* line (of assembly code) is declared matched. Note that the */
1810 /* operand may be wild too. */
1812 /* Note, a wild instruction is specified just like a wild var: */
1813 /* %4 ; A wild instruction, */
1814 /* See the peeph.def file for additional examples */
1816 /*-----------------------------------------------------------------*/
1818 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1823 pcw = Safe_calloc(1,sizeof(pCodeWild));
1825 pcw->pci.pc.type = PC_WILD;
1826 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1827 pcw->id = PCodeID();
1828 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1829 pcw->pci.pc.pb = NULL;
1831 // pcw->pci.pc.analyze = genericAnalyze;
1832 pcw->pci.pc.destruct = genericDestruct;
1833 pcw->pci.pc.print = genericPrint;
1835 pcw->id = pCodeID; // this is the 'n' in %n
1836 pcw->operand = optional_operand;
1837 pcw->label = optional_label;
1839 pcw->mustBeBitSkipInst = 0;
1840 pcw->mustNotBeBitSkipInst = 0;
1841 pcw->invertBitSkipInst = 0;
1843 return ( (pCode *)pcw);
1847 /*-----------------------------------------------------------------*/
1848 /* newPcodeInlineP - create a new pCode from a char string */
1849 /*-----------------------------------------------------------------*/
1852 pCode *newpCodeInlineP(char *cP)
1857 pcc = Safe_calloc(1,sizeof(pCodeComment));
1859 pcc->pc.type = PC_INLINE;
1860 pcc->pc.prev = pcc->pc.next = NULL;
1861 pcc->pc.id = PCodeID();
1862 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1865 // pcc->pc.analyze = genericAnalyze;
1866 pcc->pc.destruct = genericDestruct;
1867 pcc->pc.print = genericPrint;
1870 pcc->comment = Safe_strdup(cP);
1872 pcc->comment = NULL;
1874 return ( (pCode *)pcc);
1878 /*-----------------------------------------------------------------*/
1879 /* newPcodeCharP - create a new pCode from a char string */
1880 /*-----------------------------------------------------------------*/
1882 pCode *newpCodeCharP(char *cP)
1887 pcc = Safe_calloc(1,sizeof(pCodeComment));
1889 pcc->pc.type = PC_COMMENT;
1890 pcc->pc.prev = pcc->pc.next = NULL;
1891 pcc->pc.id = PCodeID();
1892 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1895 // pcc->pc.analyze = genericAnalyze;
1896 pcc->pc.destruct = genericDestruct;
1897 pcc->pc.print = genericPrint;
1900 pcc->comment = Safe_strdup(cP);
1902 pcc->comment = NULL;
1904 return ( (pCode *)pcc);
1908 /*-----------------------------------------------------------------*/
1909 /* newpCodeFunction - */
1910 /*-----------------------------------------------------------------*/
1913 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1917 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1918 //_ALLOC(pcf,sizeof(pCodeFunction));
1920 pcf->pc.type = PC_FUNCTION;
1921 pcf->pc.prev = pcf->pc.next = NULL;
1922 pcf->pc.id = PCodeID();
1923 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1926 // pcf->pc.analyze = genericAnalyze;
1927 pcf->pc.destruct = genericDestruct;
1928 pcf->pc.print = pCodePrintFunction;
1933 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1934 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1935 strcpy(pcf->modname,mod);
1937 pcf->modname = NULL;
1940 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1941 pcf->fname = Safe_calloc(1,strlen(f)+1);
1942 strcpy(pcf->fname,f);
1946 pcf->isPublic = (unsigned)isPublic;
1948 return ( (pCode *)pcf);
1952 /*-----------------------------------------------------------------*/
1954 /*-----------------------------------------------------------------*/
1955 void destructpCodeFlow(pCode *pc)
1957 if(!pc || !isPCFL(pc))
1966 deleteSet(&PCFL(pc)->registers);
1967 deleteSet(&PCFL(pc)->from);
1968 deleteSet(&PCFL(pc)->to);
1973 pCode *newpCodeFlow(void )
1977 //_ALLOC(pcflow,sizeof(pCodeFlow));
1978 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1980 pcflow->pc.type = PC_FLOW;
1981 pcflow->pc.prev = pcflow->pc.next = NULL;
1982 pcflow->pc.pb = NULL;
1984 // pcflow->pc.analyze = genericAnalyze;
1985 pcflow->pc.destruct = destructpCodeFlow;
1986 pcflow->pc.print = genericPrint;
1988 pcflow->pc.seq = GpcFlowSeq++;
1990 pcflow->from = pcflow->to = NULL;
1992 pcflow->inCond = PCC_NONE;
1993 pcflow->outCond = PCC_NONE;
1995 pcflow->firstBank = 'U'; /* Undetermined */
1996 pcflow->lastBank = 'U'; /* Undetermined */
1998 pcflow->FromConflicts = 0;
1999 pcflow->ToConflicts = 0;
2003 pcflow->registers = newSet();
2005 return ( (pCode *)pcflow);
2009 /*-----------------------------------------------------------------*/
2010 /*-----------------------------------------------------------------*/
2011 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2013 pCodeFlowLink *pcflowLink;
2015 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2017 pcflowLink->pcflow = pcflow;
2018 pcflowLink->bank_conflict = 0;
2023 /*-----------------------------------------------------------------*/
2024 /* newpCodeCSource - create a new pCode Source Symbol */
2025 /*-----------------------------------------------------------------*/
2027 pCode *newpCodeCSource(int ln, char *f, const char *l)
2032 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2034 pccs->pc.type = PC_CSOURCE;
2035 pccs->pc.prev = pccs->pc.next = NULL;
2036 pccs->pc.id = PCodeID();
2039 pccs->pc.destruct = genericDestruct;
2040 pccs->pc.print = genericPrint;
2042 pccs->line_number = ln;
2044 pccs->line = Safe_strdup(l);
2049 pccs->file_name = Safe_strdup(f);
2051 pccs->file_name = NULL;
2053 return ( (pCode *)pccs);
2057 /*******************************************************************/
2058 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2059 /* added by VR 6-Jun-2003 */
2060 /*******************************************************************/
2062 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2069 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2070 pcad->pci.pc.type = PC_ASMDIR;
2071 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2072 pcad->pci.pc.pb = NULL;
2073 pcad->pci.pc.destruct = genericDestruct;
2074 pcad->pci.pc.print = genericPrint;
2076 if(asdir && *asdir) {
2078 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2080 pcad->directive = Safe_strdup( asdir );
2083 va_start(ap, argfmt);
2085 memset(buffer, 0, sizeof(buffer));
2086 if(argfmt && *argfmt)
2087 vsprintf(buffer, argfmt, ap);
2091 while(isspace((unsigned char)*lbp))lbp++;
2094 pcad->arg = Safe_strdup( lbp );
2096 return ((pCode *)pcad);
2099 /*-----------------------------------------------------------------*/
2100 /* pCodeLabelDestruct - free memory used by a label. */
2101 /*-----------------------------------------------------------------*/
2102 static void pCodeLabelDestruct(pCode *pc)
2108 if((pc->type == PC_LABEL) && PCL(pc)->label)
2109 free(PCL(pc)->label);
2115 pCode *newpCodeLabel(char *name, int key)
2121 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2123 pcl->pc.type = PC_LABEL;
2124 pcl->pc.prev = pcl->pc.next = NULL;
2125 pcl->pc.id = PCodeID();
2126 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2129 // pcl->pc.analyze = genericAnalyze;
2130 pcl->pc.destruct = pCodeLabelDestruct;
2131 pcl->pc.print = pCodePrintLabel;
2137 sprintf(s,"_%05d_DS_",key);
2142 pcl->label = Safe_strdup(s);
2144 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2145 return ( (pCode *)pcl);
2150 /*-----------------------------------------------------------------*/
2151 /* newpBlock - create and return a pointer to a new pBlock */
2152 /*-----------------------------------------------------------------*/
2153 pBlock *newpBlock(void)
2158 PpB = Safe_calloc(1,sizeof(pBlock) );
2159 PpB->next = PpB->prev = NULL;
2161 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2162 PpB->tregisters = NULL;
2164 PpB->FlowTree = NULL;
2170 /*-----------------------------------------------------------------*/
2171 /* newpCodeChain - create a new chain of pCodes */
2172 /*-----------------------------------------------------------------*
2174 * This function will create a new pBlock and the pointer to the
2175 * pCode that is passed in will be the first pCode in the block.
2176 *-----------------------------------------------------------------*/
2179 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2182 pBlock *pB = newpBlock();
2184 pB->pcHead = pB->pcTail = pc;
2191 /*-----------------------------------------------------------------*/
2192 /* newpCodeOpLabel - Create a new label given the key */
2193 /* Note, a negative key means that the label is part of wild card */
2194 /* (and hence a wild card label) used in the pCodePeep */
2195 /* optimizations). */
2196 /*-----------------------------------------------------------------*/
2198 pCodeOp *newpCodeOpLabel(char *name, int key)
2201 static int label_key=-1;
2205 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2206 pcop->type = PO_LABEL;
2211 sprintf(s=buffer,"_%05d_DS_",key);
2213 s = name, key = label_key--;
2215 PCOLAB(pcop)->offset = 0;
2217 pcop->name = Safe_strdup(s);
2219 ((pCodeOpLabel *)pcop)->key = key;
2221 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2225 /*-----------------------------------------------------------------*/
2226 /*-----------------------------------------------------------------*/
2227 pCodeOp *newpCodeOpLit(int lit)
2233 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2234 pcop->type = PO_LITERAL;
2238 sprintf(s,"0x%02x", (unsigned char)lit);
2240 pcop->name = Safe_strdup(s);
2243 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2248 /*-----------------------------------------------------------------*/
2249 /*-----------------------------------------------------------------*/
2250 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2254 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2255 pcop->type = PO_IMMEDIATE;
2258 pcop->name = Safe_strdup(name);
2261 r = dirregWithName(name);
2265 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2266 PCOI(pcop)->rIdx = r->rIdx;
2268 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2269 PCOI(pcop)->rIdx = -1;
2271 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2276 PCOI(pcop)->index = index;
2277 PCOI(pcop)->offset = offset;
2278 PCOI(pcop)->_const = code_space;
2279 PCOI(pcop)->_function = is_func;
2284 /*-----------------------------------------------------------------*/
2285 /*-----------------------------------------------------------------*/
2286 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2292 if(!pcwb || !subtype) {
2293 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2297 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2298 pcop->type = PO_WILD;
2299 sprintf(s,"%%%d",id);
2300 pcop->name = Safe_strdup(s);
2302 PCOW(pcop)->id = id;
2303 PCOW(pcop)->pcwb = pcwb;
2304 PCOW(pcop)->subtype = subtype;
2305 PCOW(pcop)->matched = NULL;
2309 /*-----------------------------------------------------------------*/
2310 /* Find a symbol with matching name */
2311 /*-----------------------------------------------------------------*/
2312 static symbol *symFindWithName(memmap * map, const char *name)
2316 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2317 if (sym->rname && (strcmp(sym->rname,name)==0))
2323 /*-----------------------------------------------------------------*/
2324 /*-----------------------------------------------------------------*/
2325 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2330 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2331 pcop->type = PO_GPR_BIT;
2333 PCORB(pcop)->bit = ibit;
2334 PCORB(pcop)->inBitSpace = inBitSpace;
2336 if (name) r = regFindWithName(name);
2338 // Register has not been allocated - check for symbol information
2340 sym = symFindWithName(bit, name);
2341 if (!sym) sym = symFindWithName(sfrbit, name);
2342 if (!sym) sym = symFindWithName(sfr, name);
2343 if (!sym) sym = symFindWithName(reg, name);
2344 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2345 // XXX: This ignores nesting levels, but works for globals...
2346 if (!sym) sym = findSym(SymbolTab, NULL, name);
2347 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2349 r = allocNewDirReg(sym->etype,name);
2355 PCOR(pcop)->rIdx = r->rIdx;
2357 pcop->name = Safe_strdup(name);
2358 PCOR(pcop)->r = NULL;
2359 PCOR(pcop)->rIdx = 0;
2365 pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2371 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2372 pcop->name = reg->name;
2373 pcop->type = PO_GPR_BIT;
2374 PCORB(pcop)->bit = ibit;
2375 PCORB(pcop)->inBitSpace = inBitSpace;
2376 PCOR(pcop)->r = reg;
2377 PCOR(pcop)->index = 0;
2378 PCOR(pcop)->rIdx = reg->rIdx;
2383 /*-----------------------------------------------------------------*
2384 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2386 * If rIdx >=0 then a specific register from the set of registers
2387 * will be selected. If rIdx <0, then a new register will be searched
2389 *-----------------------------------------------------------------*/
2391 pCodeOp *newpCodeOpReg(int rIdx)
2395 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2400 PCOR(pcop)->rIdx = rIdx;
2401 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2403 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2406 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2410 pcop->type = PCOR(pcop)->r->pc_type;
2415 pCodeOp *newpCodeOpRegFromStr(char *name)
2419 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2420 PCOR(pcop)->r = allocRegByName(name, 1);
2421 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2422 pcop->type = PCOR(pcop)->r->pc_type;
2423 pcop->name = PCOR(pcop)->r->name;
2428 pCodeOp *newpCodeOpStr(char *name)
2432 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2433 pcop->type = PO_STR;
2434 pcop->name = Safe_strdup(name);
2436 PCOS(pcop)->isPublic = 0;
2442 /*-----------------------------------------------------------------*/
2443 /*-----------------------------------------------------------------*/
2445 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2452 pcop = newpCodeOpBit(name, -1,0);
2456 pcop = newpCodeOpLit(-1);
2460 pcop = newpCodeOpLabel(NULL,-1);
2464 pcop = newpCodeOpReg(-1);
2467 case PO_GPR_POINTER:
2468 case PO_GPR_REGISTER:
2470 pcop = newpCodeOpRegFromStr(name);
2472 pcop = newpCodeOpReg(-1);
2476 pcop = newpCodeOpStr(name);
2480 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2483 pcop->name = Safe_strdup(name);
2491 /*-----------------------------------------------------------------*/
2492 /*-----------------------------------------------------------------*/
2493 void pCodeConstString(char *name, char *value)
2498 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2503 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2507 sprintf(buffer,"; %s = %s",name,value);
2508 for (i=strlen(buffer); i--; ) {
2509 unsigned char c = buffer[i];
2510 if (c=='\r' || c=='\n') {
2511 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2513 if (c=='\r') buffer[i+1] = 'r';
2514 else if (c=='\n') buffer[i+1] = 'n';
2518 addpCode2pBlock(pb,newpCodeCharP(buffer));
2519 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2522 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2528 /*-----------------------------------------------------------------*/
2529 /*-----------------------------------------------------------------*/
2530 void pCodeReadCodeTable(void)
2534 fprintf(stderr, " %s\n",__FUNCTION__);
2536 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2540 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2541 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2542 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2543 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2545 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2546 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2547 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2548 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2553 /*-----------------------------------------------------------------*/
2554 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2555 /*-----------------------------------------------------------------*/
2556 void addpCode2pBlock(pBlock *pb, pCode *pc)
2563 /* If this is the first pcode to be added to a block that
2564 * was initialized with a NULL pcode, then go ahead and
2565 * make this pcode the head and tail */
2566 pb->pcHead = pb->pcTail = pc;
2569 pb->pcTail->next = pc;
2571 pc->prev = pb->pcTail;
2578 /*-----------------------------------------------------------------*/
2579 /* addpBlock - place a pBlock into the pFile */
2580 /*-----------------------------------------------------------------*/
2581 void addpBlock(pBlock *pb)
2583 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2586 /* First time called, we'll pass through here. */
2587 //_ALLOC(the_pFile,sizeof(pFile));
2588 the_pFile = Safe_calloc(1,sizeof(pFile));
2589 the_pFile->pbHead = the_pFile->pbTail = pb;
2590 the_pFile->functions = NULL;
2594 the_pFile->pbTail->next = pb;
2595 pb->prev = the_pFile->pbTail;
2597 the_pFile->pbTail = pb;
2600 /*-----------------------------------------------------------------*/
2601 /* removepBlock - remove a pBlock from the pFile */
2602 /*-----------------------------------------------------------------*/
2603 void removepBlock(pBlock *pb)
2611 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2613 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2616 if(pbs == the_pFile->pbHead)
2617 the_pFile->pbHead = pbs->next;
2619 if (pbs == the_pFile->pbTail)
2620 the_pFile->pbTail = pbs->prev;
2623 pbs->next->prev = pbs->prev;
2626 pbs->prev->next = pbs->next;
2633 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2637 /*-----------------------------------------------------------------*/
2638 /* printpCode - write the contents of a pCode to a file */
2639 /*-----------------------------------------------------------------*/
2640 void printpCode(FILE *of, pCode *pc)
2651 fprintf(of,"warning - unable to print pCode\n");
2654 /*-----------------------------------------------------------------*/
2655 /* printpBlock - write the contents of a pBlock to a file */
2656 /*-----------------------------------------------------------------*/
2657 void printpBlock(FILE *of, pBlock *pb)
2667 for(pc = pb->pcHead; pc; pc = pc->next) {
2672 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2682 /*-----------------------------------------------------------------*/
2684 /* pCode processing */
2688 /*-----------------------------------------------------------------*/
2690 void unlinkpCode(pCode *pc)
2696 fprintf(stderr,"Unlinking: ");
2697 printpCode(stderr, pc);
2700 pc->prev->next = pc->next;
2702 pc->next->prev = pc->prev;
2705 /* RN: I believe this should be right here, but this did not
2706 * cure the bug I was hunting... */
2707 /* must keep labels -- attach to following instruction */
2708 if (isPCI(pc) && PCI(pc)->label && pc->next)
2710 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2713 pBranchAppend (pcnext->label, PCI(pc)->label);
2717 pc->prev = pc->next = NULL;
2721 /*-----------------------------------------------------------------*/
2722 /*-----------------------------------------------------------------*/
2724 static void genericDestruct(pCode *pc)
2730 /* For instructions, tell the register (if there's one used)
2731 * that it's no longer needed */
2732 regs *reg = getRegFromInstruction(pc);
2734 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2737 /* Instead of deleting the memory used by this pCode, mark
2738 * the object as bad so that if there's a pointer to this pCode
2739 * dangling around somewhere then (hopefully) when the type is
2740 * checked we'll catch it.
2745 addpCode2pBlock(pb_dead_pcodes, pc);
2752 /*-----------------------------------------------------------------*/
2753 /* Copies the pCodeInstruction flow pointer from source pCode */
2754 /*-----------------------------------------------------------------*/
2755 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2757 pCodeFlow *pcflow = 0;
2758 for (p=pcs; p; p=p->prev) {
2760 pcflow = PCI(p)->pcflow;
2764 pcflow = (pCodeFlow*)p;
2768 PCI(pcd)->pcflow = pcflow;
2771 /*-----------------------------------------------------------------*/
2772 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2773 /* into the pCode chain containing pc1 */
2774 /*-----------------------------------------------------------------*/
2775 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2781 pc2->next = pc1->next;
2783 pc1->next->prev = pc2;
2789 /* If this is an instrution type propogate the flow */
2791 CopyFlow(PCI(pc2),pc1);
2794 /*------------------------------------------------------------------*/
2795 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2796 /* into the pCode chain containing pc1 */
2797 /*------------------------------------------------------------------*/
2798 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2804 pc2->prev = pc1->prev;
2806 pc1->prev->next = pc2;
2812 /* If this is an instrution type propogate the flow */
2814 CopyFlow(PCI(pc2),pc1);
2817 /*-----------------------------------------------------------------*/
2818 /* pCodeOpCopy - copy a pcode operator */
2819 /*-----------------------------------------------------------------*/
2820 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2822 pCodeOp *pcopnew=NULL;
2827 switch(pcop->type) {
2830 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2831 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2839 case PO_GPR_REGISTER:
2841 case PO_GPR_POINTER:
2842 case PO_SFR_REGISTER:
2846 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2847 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2848 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2849 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2853 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2854 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2855 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2859 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2860 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2866 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2867 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2868 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2872 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2873 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2874 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2878 /* Here we expand the wild card into the appropriate type: */
2879 /* By recursively calling pCodeOpCopy */
2880 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2881 if(PCOW(pcop)->matched)
2882 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2885 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2886 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2887 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2894 assert ( !"unhandled pCodeOp type copied" );
2899 pcopnew->name = Safe_strdup(pcop->name);
2901 pcopnew->name = NULL;
2906 /*-----------------------------------------------------------------*/
2907 /* popCopyReg - copy a pcode operator */
2908 /*-----------------------------------------------------------------*/
2909 pCodeOp *popCopyReg(pCodeOpReg *pc)
2913 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2914 pcor->pcop.type = pc->pcop.type;
2916 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2917 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2919 pcor->pcop.name = NULL;
2921 if (pcor->pcop.type == PO_IMMEDIATE){
2922 PCOL(pcor)->lit = PCOL(pc)->lit;
2925 pcor->rIdx = pc->rIdx;
2929 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2934 /*-----------------------------------------------------------------*/
2935 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2936 /*-----------------------------------------------------------------*/
2937 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2939 pCodeInstruction *new_pci;
2942 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2944 new_pci = PCI(newpCode(pci->op,pci->pcop));
2946 new_pci->pc.pb = pci->pc.pb;
2947 new_pci->from = pci->from;
2948 new_pci->to = pci->to;
2949 new_pci->label = pci->label;
2950 new_pci->pcflow = pci->pcflow;
2952 return PCODE(new_pci);
2955 /*-----------------------------------------------------------------*/
2956 /*-----------------------------------------------------------------*/
2957 void pCodeDeleteChain(pCode *f,pCode *t)
2962 DFPRINTF((stderr,"delete pCode:\n"));
2964 //f->print(stderr,f);
2965 //f->delete(f); this dumps core...
2970 /*-----------------------------------------------------------------*/
2971 /*-----------------------------------------------------------------*/
2972 void pBlockRegs(FILE *of, pBlock *pb)
2977 r = setFirstItem(pb->tregisters);
2979 r = setNextItem(pb->tregisters);
2984 /*-----------------------------------------------------------------*/
2985 /*-----------------------------------------------------------------*/
2986 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2991 int use_buffer = 1; // copy the string to the passed buffer pointer
2996 use_buffer = 0; // Don't bother copying the string to the buffer.
3000 switch(pcop->type) {
3004 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3007 //return PCOR(pcop)->r->name;
3011 if (PCOR(pcop)->r->type == REG_STK)
3012 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3014 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3017 SAFE_snprintf(&buffer,&size,"%s",r->name);
3026 if(PCOI(pcop)->_const) {
3028 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3029 switch(PCOI(pcop)->offset) {
3031 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3034 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3037 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3040 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3041 assert ( !"offset too large" );
3042 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3045 8 * PCOI(pcop)->offset );
3048 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3050 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3051 SAFE_snprintf(&s,&size,"(%s + %d)",
3055 switch(PCOI(pcop)->offset) {
3057 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3060 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3063 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3066 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3067 assert ( !"offset too large" );
3068 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3078 //size = sizeof(buffer);
3079 if( PCOR(pcop)->instance) {
3080 SAFE_snprintf(&s,&size,"(%s + %d)",
3082 PCOR(pcop)->instance );
3083 //fprintf(stderr,"PO_DIR %s\n",buffer);
3085 SAFE_snprintf(&s,&size,"%s",pcop->name);
3091 if(PCOLAB(pcop)->offset == 1)
3092 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3094 SAFE_snprintf(&s,&size,"%s",pcop->name);
3101 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3104 return PCOR(pcop)->r->name;
3107 /* fall through to the default case */
3111 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3119 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3120 __FILE__, __LINE__, __FUNCTION__,
3123 return "NO operand";
3127 /*-----------------------------------------------------------------*/
3128 /*-----------------------------------------------------------------*/
3129 static char *get_op_from_instruction( pCodeInstruction *pcc)
3133 return get_op(pcc->pcop,NULL,0);
3135 return ("ERROR Null: get_op_from_instruction");
3139 /*-----------------------------------------------------------------*/
3140 /*-----------------------------------------------------------------*/
3141 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3143 fprintf(of,"pcodeopprint- not implemented\n");
3146 /*-----------------------------------------------------------------*/
3147 /* pCode2str - convert a pCode instruction to string */
3148 /*-----------------------------------------------------------------*/
3149 char *pCode2str(char *str, size_t size, pCode *pc)
3157 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3159 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3161 if(PCI(pc)->isBitInst) {
3162 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3163 char *name = PCI(pc)->pcop->name;
3165 name = PCOR(PCI(pc)->pcop)->r->name;
3166 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3167 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3169 SAFE_snprintf(&s,&size,"%s,%d", name,
3170 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3171 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3172 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3174 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3175 //PCI(pc)->pcop->t.bit );
3177 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3178 if( PCI(pc)->num_ops == 2)
3179 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3181 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3183 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3184 if( PCI(pc)->num_ops == 2)
3185 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3192 /* assuming that comment ends with a \n */
3193 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3197 /* assuming that inline code ends with a \n */
3198 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3202 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3205 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3208 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3211 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3214 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3215 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);
3218 if(PCAD(pc)->directive) {
3219 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3220 } else if(PCAD(pc)->arg) {
3221 /* special case to handle inline labels without a tab */
3222 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3227 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3233 /*-----------------------------------------------------------------*/
3234 /* genericPrint - the contents of a pCode to a file */
3235 /*-----------------------------------------------------------------*/
3236 static void genericPrint(FILE *of, pCode *pc)
3243 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3247 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3251 // If the opcode has a label, print that first
3254 pCodeInstruction *pci = PCI(pc);
3255 pBranch *pbl = pci->label;
3256 while(pbl && pbl->pc) {
3257 if(pbl->pc->type == PC_LABEL)
3258 pCodePrintLabel(of, pbl->pc);
3263 genericPrint(of,PCODE(pci->cline));
3266 pCode2str(str, 256, pc);
3268 fprintf(of,"%s",str);
3272 pCodeOpReg *pcor = PCOR(pci->pcop);
3273 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3275 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3276 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3277 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3282 pBranch *dpb = pc->to; // debug
3284 switch ( dpb->pc->type) {
3286 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3289 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3292 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3295 fprintf(of, "\t;flow");
3309 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3310 if(PCW(pc)->pci.label)
3311 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3313 if(PCW(pc)->operand) {
3314 fprintf(of,";\toperand ");
3315 pCodeOpPrint(of,PCW(pc)->operand );
3321 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3322 if(PCFL(pc)->ancestor)
3323 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3325 fprintf(of,"; from: ");
3327 pCodeFlowLink *link;
3328 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3330 fprintf(of,"%03x ",link->pcflow->pc.seq);
3333 fprintf(of,"; to: ");
3335 pCodeFlowLink *link;
3336 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3338 fprintf(of,"%03x ",link->pcflow->pc.seq);
3346 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3347 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3352 pBranch *pbl = PCAD(pc)->pci.label;
3353 while(pbl && pbl->pc) {
3354 if(pbl->pc->type == PC_LABEL)
3355 pCodePrintLabel(of, pbl->pc);
3359 if(PCAD(pc)->directive) {
3360 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3363 /* special case to handle inline labels without tab */
3364 fprintf(of, "%s\n", PCAD(pc)->arg);
3370 fprintf(of,"unknown pCode type %d\n",pc->type);
3374 /*-----------------------------------------------------------------*/
3375 /* pCodePrintFunction - prints function begin/end */
3376 /*-----------------------------------------------------------------*/
3378 static void pCodePrintFunction(FILE *of, pCode *pc)
3384 if( ((pCodeFunction *)pc)->modname)
3385 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3387 if(PCF(pc)->fname) {
3388 pBranch *exits = PCF(pc)->to;
3390 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3393 exits = exits->next;
3396 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3399 if((PCF(pc)->from &&
3400 PCF(pc)->from->pc->type == PC_FUNCTION &&
3401 PCF(PCF(pc)->from->pc)->fname) )
3402 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3404 fprintf(of,"; exit point [can't find entry point]\n");
3407 /*-----------------------------------------------------------------*/
3408 /* pCodePrintLabel - prints label */
3409 /*-----------------------------------------------------------------*/
3411 static void pCodePrintLabel(FILE *of, pCode *pc)
3418 fprintf(of,"%s\n",PCL(pc)->label);
3419 else if (PCL(pc)->key >=0)
3420 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3422 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3426 /*-----------------------------------------------------------------*/
3427 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3428 /* remove it if it is found. */
3429 /*-----------------------------------------------------------------*/
3430 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3436 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3437 b = PCI(pcl)->label;
3439 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3443 //fprintf (stderr, "%s \n",__FUNCTION__);
3444 //pcl->print(stderr,pcl);
3445 //pc->print(stderr,pc);
3448 //fprintf (stderr, "found label\n");
3452 bprev->next = b->next; /* Not first pCode in chain */
3456 PCI(pcl)->label = b->next; /* First pCode in chain */
3459 return; /* A label can't occur more than once */
3466 /*-----------------------------------------------------------------*/
3467 /*-----------------------------------------------------------------*/
3468 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3487 /*-----------------------------------------------------------------*/
3488 /* pBranchLink - given two pcodes, this function will link them */
3489 /* together through their pBranches */
3490 /*-----------------------------------------------------------------*/
3491 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3495 // Declare a new branch object for the 'from' pCode.
3497 //_ALLOC(b,sizeof(pBranch));
3498 b = Safe_calloc(1,sizeof(pBranch));
3499 b->pc = PCODE(t); // The link to the 'to' pCode.
3502 f->to = pBranchAppend(f->to,b);
3504 // Now do the same for the 'to' pCode.
3506 //_ALLOC(b,sizeof(pBranch));
3507 b = Safe_calloc(1,sizeof(pBranch));
3511 t->from = pBranchAppend(t->from,b);
3516 /*-----------------------------------------------------------------*/
3517 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3519 /*-----------------------------------------------------------------*/
3520 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3533 /*-----------------------------------------------------------------*/
3534 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3535 /*-----------------------------------------------------------------*/
3536 static void pCodeUnlink(pCode *pc)
3541 if(!pc->prev || !pc->next) {
3542 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3546 /* first remove the pCode from the chain */
3547 pc->prev->next = pc->next;
3548 pc->next->prev = pc->prev;
3550 /* Now for the hard part... */
3552 /* Remove the branches */
3556 pc1 = pb1->pc; /* Get the pCode that branches to the
3557 * one we're unlinking */
3559 /* search for the link back to this pCode (the one we're
3561 if(pb2 = pBranchFind(pc1->to,pc)) {
3562 pb2->pc = pc->to->pc; // make the replacement
3564 /* if the pCode we're unlinking contains multiple 'to'
3565 * branches (e.g. this a skip instruction) then we need
3566 * to copy these extra branches to the chain. */
3568 pBranchAppend(pb2, pc->to->next);
3577 /*-----------------------------------------------------------------*/
3578 /*-----------------------------------------------------------------*/
3580 static void genericAnalyze(pCode *pc)
3590 // Go through the pCodes that are in pCode chain and link
3591 // them together through the pBranches. Note, the pCodes
3592 // are linked together as a contiguous stream like the
3593 // assembly source code lines. The linking here mimics this
3594 // except that comments are not linked in.
3596 pCode *npc = pc->next;
3598 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3599 pBranchLink(pc,npc);
3604 /* reached the end of the pcode chain without finding
3605 * an instruction we could link to. */
3609 fprintf(stderr,"analyze PC_FLOW\n");
3613 fprintf(stderr,";A bad pCode is being used\n");
3619 /*-----------------------------------------------------------------*/
3620 /*-----------------------------------------------------------------*/
3621 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3625 if(pc->type == PC_LABEL) {
3626 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3629 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3630 pbr = PCI(pc)->label;
3632 if(pbr->pc->type == PC_LABEL) {
3633 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3643 /*-----------------------------------------------------------------*/
3644 /*-----------------------------------------------------------------*/
3645 int checkLabel(pCode *pc)
3649 if(pc && isPCI(pc)) {
3650 pbr = PCI(pc)->label;
3652 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3662 /*-----------------------------------------------------------------*/
3663 /* findLabelinpBlock - Search the pCode for a particular label */
3664 /*-----------------------------------------------------------------*/
3665 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3672 for(pc = pb->pcHead; pc; pc = pc->next)
3673 if(compareLabel(pc,pcop_label))
3679 /*-----------------------------------------------------------------*/
3680 /* findLabel - Search the pCode for a particular label */
3681 /*-----------------------------------------------------------------*/
3682 pCode * findLabel(pCodeOpLabel *pcop_label)
3690 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3691 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3695 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3699 /*-----------------------------------------------------------------*/
3700 /* findNextpCode - given a pCode, find the next of type 'pct' */
3701 /* in the linked list */
3702 /*-----------------------------------------------------------------*/
3703 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3716 /*-----------------------------------------------------------------*/
3717 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3718 /* in the linked list */
3719 /*-----------------------------------------------------------------*/
3720 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3724 if(pc->type == pct) {
3726 static unsigned int stop;
3728 stop++; // Place break point here
3739 /*-----------------------------------------------------------------*/
3740 /* findNextInstruction - given a pCode, find the next instruction */
3741 /* in the linked list */
3742 /*-----------------------------------------------------------------*/
3743 pCode * findNextInstruction(pCode *pci)
3748 if((pc->type == PC_OPCODE)
3749 || (pc->type == PC_WILD)
3750 || (pc->type == PC_ASMDIR))
3754 fprintf(stderr,"findNextInstruction: ");
3755 printpCode(stderr, pc);
3760 //fprintf(stderr,"Couldn't find instruction\n");
3764 /*-----------------------------------------------------------------*/
3765 /* findNextInstruction - given a pCode, find the next instruction */
3766 /* in the linked list */
3767 /*-----------------------------------------------------------------*/
3768 pCode * findPrevInstruction(pCode *pci)
3774 if((pc->type == PC_OPCODE)
3775 || (pc->type == PC_WILD)
3776 || (pc->type == PC_ASMDIR))
3781 fprintf(stderr,"pic16_findPrevInstruction: ");
3782 printpCode(stderr, pc);
3787 //fprintf(stderr,"Couldn't find instruction\n");
3791 /*-----------------------------------------------------------------*/
3792 /* findFunctionEnd - given a pCode find the end of the function */
3793 /* that contains it */
3794 /*-----------------------------------------------------------------*/
3795 pCode * findFunctionEnd(pCode *pc)
3798 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3804 fprintf(stderr,"Couldn't find function end\n");
3809 /*-----------------------------------------------------------------*/
3810 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3811 /* instruction with which it is associated. */
3812 /*-----------------------------------------------------------------*/
3813 static void AnalyzeLabel(pCode *pc)
3822 static void AnalyzeGOTO(pCode *pc)
3825 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3829 static void AnalyzeSKIP(pCode *pc)
3832 pBranchLink(pc,findNextInstruction(pc->next));
3833 pBranchLink(pc,findNextInstruction(pc->next->next));
3837 static void AnalyzeRETURN(pCode *pc)
3840 // branch_link(pc,findFunctionEnd(pc->next));
3846 /*-----------------------------------------------------------------*/
3847 /*-----------------------------------------------------------------*/
3848 regs * getRegFromInstruction(pCode *pc)
3854 PCI(pc)->num_ops == 0 )
3857 switch(PCI(pc)->pcop->type) {
3864 case PO_SFR_REGISTER:
3867 return PCOR(PCI(pc)->pcop)->r;
3869 case PO_GPR_REGISTER:
3872 r = PCOR(PCI(pc)->pcop)->r;
3875 return dirregWithName(PCI(pc)->pcop->name);
3881 r = PCOI(PCI(pc)->pcop)->r;
3884 return dirregWithName(PCI(pc)->pcop->name);
3894 /*-----------------------------------------------------------------*/
3895 /*-----------------------------------------------------------------*/
3897 void AnalyzepBlock(pBlock *pb)
3904 /* Find all of the registers used in this pBlock
3905 * by looking at each instruction and examining it's
3908 for(pc = pb->pcHead; pc; pc = pc->next) {
3910 /* Is this an instruction with operands? */
3911 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3913 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3914 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3916 /* Loop through all of the registers declared so far in
3917 this block and see if we find this one there */
3919 regs *r = setFirstItem(pb->tregisters);
3922 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3923 PCOR(PCI(pc)->pcop)->r = r;
3926 r = setNextItem(pb->tregisters);
3930 /* register wasn't found */
3931 //r = Safe_calloc(1, sizeof(regs));
3932 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3933 //addSet(&pb->tregisters, r);
3934 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3935 //PCOR(PCI(pc)->pcop)->r = r;
3936 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3938 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3941 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3942 if(PCOR(PCI(pc)->pcop)->r) {
3943 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3944 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3946 if(PCI(pc)->pcop->name)
3947 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3949 fprintf(stderr,"ERROR: NULL register\n");
3958 /*-----------------------------------------------------------------*/
3960 /*-----------------------------------------------------------------*/
3961 void InsertpFlow(pCode *pc, pCode **pflow)
3964 PCFL(*pflow)->end = pc;
3966 if(!pc || !pc->next)
3969 *pflow = newpCodeFlow();
3970 pCodeInsertAfter(pc, *pflow);
3973 /*-----------------------------------------------------------------*/
3974 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3975 /* the flow blocks. */
3977 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3978 * point the instruction flow changes.
3980 /*-----------------------------------------------------------------*/
3981 void BuildFlow(pBlock *pb)
3984 pCode *last_pci=NULL;
3991 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3992 /* Insert a pCodeFlow object at the beginning of a pBlock */
3994 InsertpFlow(pb->pcHead, &pflow);
3996 //pflow = newpCodeFlow(); /* Create a new Flow object */
3997 //pflow->next = pb->pcHead; /* Make the current head the next object */
3998 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3999 //pb->pcHead = pflow; /* Make the Flow object the head */
4002 for( pc = findNextInstruction(pb->pcHead);
4004 pc=findNextInstruction(pc)) {
4007 PCI(pc)->pcflow = PCFL(pflow);
4009 //fprintf(stderr," build: ");
4010 //pc->print(stderr, pc);
4011 //pflow->print(stderr,pflow);
4013 if (checkLabel(pc)) {
4015 /* This instruction marks the beginning of a
4016 * new flow segment */
4021 /* If the previous pCode is not a flow object, then
4022 * insert a new flow object. (This check prevents
4023 * two consecutive flow objects from being insert in
4024 * the case where a skip instruction preceeds an
4025 * instruction containing a label.) */
4027 last_pci = findPrevInstruction (pc->prev);
4029 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4030 InsertpFlow(last_pci, &pflow);
4032 PCI(pc)->pcflow = PCFL(pflow);
4036 if(isPCI_SKIP(pc)) {
4038 /* The two instructions immediately following this one
4039 * mark the beginning of a new flow segment */
4041 while(pc && isPCI_SKIP(pc)) {
4043 PCI(pc)->pcflow = PCFL(pflow);
4047 InsertpFlow(pc, &pflow);
4048 pc=findNextInstruction(pc->next);
4056 PCI(pc)->pcflow = PCFL(pflow);
4058 InsertpFlow(pc, &pflow);
4060 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4062 InsertpFlow(pc, &pflow);
4071 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4073 PCFL(pflow)->end = pb->pcTail;
4076 /*-------------------------------------------------------------------*/
4077 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4078 /* the flow blocks. */
4080 * unBuildFlow removes pCodeFlow objects from a pCode chain
4082 /*-----------------------------------------------------------------*/
4083 void unBuildFlow(pBlock *pb)
4098 if(PCI(pc)->pcflow) {
4099 //free(PCI(pc)->pcflow);
4100 PCI(pc)->pcflow = NULL;
4103 } else if(isPCFL(pc) )
4112 /*-----------------------------------------------------------------*/
4113 /*-----------------------------------------------------------------*/
4114 void dumpCond(int cond)
4117 static char *pcc_str[] = {
4131 int ncond = sizeof(pcc_str) / sizeof(char *);
4134 fprintf(stderr, "0x%04X\n",cond);
4136 for(i=0,j=1; i<ncond; i++, j<<=1)
4138 fprintf(stderr, " %s\n",pcc_str[i]);
4142 /*-----------------------------------------------------------------*/
4143 /*-----------------------------------------------------------------*/
4144 void FlowStats(pCodeFlow *pcflow)
4152 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4154 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4157 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4162 fprintf(stderr, " FlowStats inCond: ");
4163 dumpCond(pcflow->inCond);
4164 fprintf(stderr, " FlowStats outCond: ");
4165 dumpCond(pcflow->outCond);
4169 /*-----------------------------------------------------------------*
4170 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4171 * if it affects the banking bits.
4173 * return: -1 == Banking bits are unaffected by this pCode.
4175 * return: > 0 == Banking bits are affected.
4177 * If the banking bits are affected, then the returned value describes
4178 * which bits are affected and how they're affected. The lower half
4179 * of the integer maps to the bits that are affected, the upper half
4180 * to whether they're set or cleared.
4182 *-----------------------------------------------------------------*/
4184 #define SET_BANK_BIT (1 << 16)
4185 #define CLR_BANK_BIT 0
4187 static int isBankInstruction(pCode *pc)
4195 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4197 // Check to see if the register banks are changing
4198 if(PCI(pc)->isModReg) {
4200 pCodeOp *pcop = PCI(pc)->pcop;
4201 switch(PCI(pc)->op) {
4204 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4205 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4206 return SET_BANK_BIT | PIC_RP0_BIT;
4209 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4210 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4211 return CLR_BANK_BIT | PIC_RP0_BIT;
4216 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4217 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4218 return CLR_BANK_BIT | PIC_RP1_BIT;
4220 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4221 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4222 return CLR_BANK_BIT | PIC_RP1_BIT;
4226 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4227 //genericPrint(stderr, pc);
4238 /*-----------------------------------------------------------------*/
4239 /*-----------------------------------------------------------------*/
4241 static void FillFlow(pCodeFlow *pcflow)
4249 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4251 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4254 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4261 isBankInstruction(pc);
4263 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4266 fprintf(stderr, " FillFlow - Bad end of flow\n");
4268 fprintf(stderr, " FillFlow - Ending flow with\n ");
4269 pc->print(stderr,pc);
4272 fprintf(stderr, " FillFlow inCond: ");
4273 dumpCond(pcflow->inCond);
4274 fprintf(stderr, " FillFlow outCond: ");
4275 dumpCond(pcflow->outCond);
4280 /*-----------------------------------------------------------------*/
4281 /*-----------------------------------------------------------------*/
4282 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4284 pCodeFlowLink *fromLink, *toLink;
4286 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4287 if (from) from->pc.print(stderr, &from->pc);
4288 else fprintf(stderr, "(null)");
4289 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4290 from && from->pcflow ? from->pcflow->pc.seq : 0,
4291 to && to->pcflow ? to->pcflow->pc.seq : 0);
4292 if (to) to->pc.print(stderr, &to->pc);
4293 else fprintf(stderr, "(null)");
4296 if(!from || !to || !to->pcflow || !from->pcflow)
4299 fromLink = newpCodeFlowLink(from->pcflow);
4300 toLink = newpCodeFlowLink(to->pcflow);
4302 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4303 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4307 /*-----------------------------------------------------------------*
4308 * void LinkFlow(pBlock *pb)
4310 * In BuildFlow, the PIC code has been partitioned into contiguous
4311 * non-branching segments. In LinkFlow, we determine the execution
4312 * order of these segments. For example, if one of the segments ends
4313 * with a skip, then we know that there are two possible flow segments
4314 * to which control may be passed.
4315 *-----------------------------------------------------------------*/
4316 void LinkFlow(pBlock *pb)
4322 //fprintf(stderr,"linkflow \n");
4324 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4326 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4329 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4331 //fprintf(stderr," link: ");
4332 //pcflow->print(stderr,pcflow);
4334 //FillFlow(PCFL(pcflow));
4336 /* find last instruction in flow */
4337 pc = findPrevInstruction (PCFL(pcflow)->end);
4339 fprintf(stderr, "%s: flow without end (%u)?\n",
4340 __FUNCTION__, pcflow->seq );
4344 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4345 //pc->print(stderr, pc);
4346 if(isPCI_SKIP(pc)) {
4347 //fprintf(stderr, "ends with skip\n");
4348 //pc->print(stderr,pc);
4349 pct=findNextInstruction(pc->next);
4350 LinkFlow_pCode(PCI(pc),PCI(pct));
4351 pct=findNextInstruction(pct->next);
4352 LinkFlow_pCode(PCI(pc),PCI(pct));
4356 if(isPCI_BRANCH(pc)) {
4357 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4359 //fprintf(stderr, "ends with branch\n ");
4360 //pc->print(stderr,pc);
4362 if(!(pcol && isPCOLAB(pcol))) {
4363 if((PCI(pc)->op != POC_RETLW)
4364 && (PCI(pc)->op != POC_RETURN)
4365 && (PCI(pc)->op != POC_CALL)
4366 && (PCI(pc)->op != POC_RETFIE) )
4368 pc->print(stderr,pc);
4369 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4373 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4374 LinkFlow_pCode(PCI(pc),PCI(pct));
4376 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4377 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4378 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4380 /* link CALLs to next instruction */
4381 if (PCI(pc)->op != POC_CALL) continue;
4385 //fprintf(stderr, "ends with non-branching instruction:\n");
4386 //pc->print(stderr,pc);
4388 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4394 //fprintf(stderr, "ends with unknown\n");
4395 //pc->print(stderr,pc);
4399 fprintf(stderr, "ends with nothing: ERROR\n");
4403 /*-----------------------------------------------------------------*/
4404 /*-----------------------------------------------------------------*/
4406 /*-----------------------------------------------------------------*/
4407 /*-----------------------------------------------------------------*/
4408 int isPCinFlow(pCode *pc, pCode *pcflow)
4414 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4417 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4423 /*-----------------------------------------------------------------*/
4424 /*-----------------------------------------------------------------*/
4426 static void BanksUsedFlow2(pCode *pcflow)
4435 if(!isPCFL(pcflow)) {
4436 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4440 pc = findNextInstruction(pcflow->next);
4442 PCFL(pcflow)->lastBank = -1;
4444 while(isPCinFlow(pc,pcflow)) {
4446 int bank_selected = isBankInstruction(pc);
4448 //if(PCI(pc)->pcflow)
4449 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4451 if(bank_selected > 0) {
4452 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4454 // This instruction is modifying banking bits before accessing registers
4456 PCFL(pcflow)->firstBank = -1;
4458 if(PCFL(pcflow)->lastBank == -1)
4459 PCFL(pcflow)->lastBank = 0;
4461 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4462 if(bank_selected & SET_BANK_BIT)
4463 PCFL(pcflow)->lastBank |= bank;
4467 reg = getRegFromInstruction(pc);
4469 if(reg && !isREGinBank(reg, bank)) {
4470 int allbanks = REGallBanks(reg);
4472 PCFL(pcflow)->firstBank = allbanks;
4474 PCFL(pcflow)->lastBank = allbanks;
4481 pc = findNextInstruction(pc->next);
4484 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4485 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4488 /*-----------------------------------------------------------------*/
4489 /*-----------------------------------------------------------------*/
4491 static void BanksUsedFlow(pBlock *pb)
4496 //pb->pcHead->print(stderr, pb->pcHead);
4498 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4499 //pcflow->print(stderr,pcflow);
4501 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4503 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4505 BanksUsedFlow2(pcflow);
4511 void pCodeReplace (pCode *old, pCode *new)
4513 pCodeInsertAfter (old, new);
4515 /* special handling for pCodeInstructions */
4516 if (isPCI(new) && isPCI(old))
4518 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4519 PCI(new)->from = PCI(old)->from;
4520 PCI(new)->to = PCI(old)->to;
4521 PCI(new)->label = PCI(old)->label;
4522 PCI(new)->pcflow = PCI(old)->pcflow;
4523 PCI(new)->cline = PCI(old)->cline;
4526 old->destruct (old);
4529 /*-----------------------------------------------------------------*/
4530 /*-----------------------------------------------------------------*/
4531 void addpCodeComment(pCode *pc, const char *fmt, ...)
4538 if (options.verbose || debug_verbose) {
4541 vsprintf(&buffer[2], fmt, ap);
4543 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4544 pCodeInsertAfter(pc, newpc);
4549 void pBlockMergeLabels(pBlock *pb);
4550 /*-----------------------------------------------------------------*/
4551 /* Inserts a new pCodeInstruction before an existing one */
4552 /*-----------------------------------------------------------------*/
4553 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4557 pcprev = findPrevInstruction(pci->pc.prev);
4559 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4561 /* Move the label, if there is one */
4564 new_pci->label = pci->label;
4568 /* Move the C code comment, if there is one */
4571 new_pci->cline = pci->cline;
4575 /* The new instruction has the same pcflow block */
4576 new_pci->pcflow = pci->pcflow;
4578 /* Arrrrg: is pci's previous instruction is a skip, we need to
4579 * change that into a jump (over pci and the new instruction) ... */
4580 if (pcprev && isPCI_SKIP(pcprev))
4582 symbol *lbl = newiTempLabel (NULL);
4583 pCode *label = newpCodeLabel (NULL, lbl->key);
4584 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4586 pCodeInsertAfter (pcprev, jump);
4588 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4589 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4590 switch (PCI(pcprev)->op) {
4595 // These are turned into non-skipping instructions, so
4596 // insert 'BTFSC STATUS, Z' after pcprev
4597 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4600 // no special actions required
4603 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4605 pCodeInsertAfter((pCode*)pci, label);
4606 pBlockMergeLabels(pci->pc.pb);
4610 /*-----------------------------------------------------------------*/
4611 /*-----------------------------------------------------------------*/
4612 static void insertBankSel(pCodeInstruction *pci, const char *name)
4618 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4619 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4621 pcop = popCopyReg(PCOR(pci->pcop));
4622 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4623 if (pcop->name == 0)
4624 pcop->name = strdup(name);
4625 new_pc = newpCode(POC_BANKSEL, pcop);
4627 insertPCodeInstruction(pci, PCI(new_pc));
4630 /*-----------------------------------------------------------------*/
4631 /*-----------------------------------------------------------------*/
4632 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4634 if (!cur_bank) return 0;
4636 // identify '(regname + X)' and 'regname'
4637 if (reg && reg->name && reg->name[0] == '(' && !strncmp(®->name[1], cur_bank, strlen(cur_bank))) return 1;
4638 if (new_bank && new_bank[0] == '(' && !strncmp(&new_bank[1], cur_bank, strlen(cur_bank))) return 1;
4639 if (cur_bank[0] == '(' && reg && reg->name && !strncmp(reg->name, &cur_bank[1], strlen(reg->name))) return 1;
4640 if (cur_bank[0] == '(' && new_bank && !strncmp(new_bank, &cur_bank[1], strlen(new_bank))) return 1;
4642 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4643 return 1; // if we have address info, we use it for banksel optimization
4645 // XXX: identify '(regname + X)' and '(regname + Y)'
4647 return ((reg && reg->name && !strcmp(reg->name, cur_bank)) || (new_bank && !strcmp(new_bank, cur_bank)));
4650 /*-----------------------------------------------------------------*/
4651 /*-----------------------------------------------------------------*/
4652 void FixRegisterBanking(pBlock *pb)
4655 pCodeInstruction *pci;
4657 regs *previous_reg; // contains the previous variable access info
4658 const char *cur_bank, *new_bank;
4659 unsigned cur_mask, new_mask, max_mask;
4664 max_mask = pic14_getPIC()->bankMask;
4665 cur_mask = max_mask;
4667 previous_reg = NULL;
4669 allRAMmshared = pic14_allRAMShared();
4671 for (pc = pb->pcHead; pc; pc = pc->next)
4673 // this one has a label---might check bank at all jumps here...
4674 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4675 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4676 previous_reg = NULL;
4677 cur_bank = NULL; // start new flow
4678 cur_mask = max_mask;
4681 // this one is/might be a label or BANKSEL---assume nothing
4682 if (isPCL(pc) || isPCASMDIR(pc)) {
4683 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4684 previous_reg = NULL;
4686 cur_mask = max_mask;
4689 // this one modifies STATUS
4690 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4694 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4695 // might need a BANKSEL
4696 reg = getRegFromInstruction(pc);
4699 new_bank = reg->name;
4700 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4701 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4702 new_mask = reg->alias;
4703 } else if (pci->pcop && pci->pcop->name) {
4704 new_bank = pci->pcop->name;
4705 new_mask = 0; // unknown, assume worst case
4707 assert(!"Could not get register from instruction.");
4711 // XXX: add switch to disable these
4713 // reg present in all banks possibly selected?
4714 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4715 // no BANKSEL required
4716 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4720 // only one bank of memory and no SFR accessed?
4721 // XXX: We can do better with fixed registers.
4722 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4723 // no BANKSEL required
4724 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4728 // restrict cur_mask to cover only the banks this register
4729 // is in (as well as the previous registers)
4730 cur_mask &= new_mask;
4732 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4733 // no BANKSEL required
4734 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4739 cur_mask = new_mask;
4740 cur_bank = new_bank;
4742 insertBankSel(pci, cur_bank);
4748 /*-----------------------------------------------------------------*/
4749 /*-----------------------------------------------------------------*/
4750 int OptimizepBlock(pBlock *pb)
4755 if(!pb || options.nopeep)
4758 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4760 for(pc = pb->pcHead; pc; pc = pc->next)
4761 matches += pCodePeepMatchRule(pc);
4764 pc = findNextInstruction(pb->pcHead);
4772 if(pCodePeepMatchRule(pc)) {
4777 pc = findNextInstruction(pcprev->next);
4779 pc = findNextInstruction(pb->pcHead);
4781 pc = findNextInstruction(pc->next);
4785 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4790 /*-----------------------------------------------------------------*/
4791 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4792 /*-----------------------------------------------------------------*/
4793 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4797 for(pc = pcs; pc; pc = pc->next) {
4799 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4801 (PCI(pc)->pcop->type == PO_LABEL) &&
4802 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4809 /*-----------------------------------------------------------------*/
4810 /*-----------------------------------------------------------------*/
4811 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4818 (PCI(pc)->pcop->type == PO_LABEL)) {
4820 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4822 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4824 free(pcol->pcop.name);
4826 /* If the key is negative, then we (probably) have a label to
4827 * a function and the name is already defined */
4830 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4834 //sprintf(buffer,"_%05d_DS_",pcl->key);
4836 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4838 pcol->pcop.name = Safe_strdup(s);
4839 pcol->key = pcl->key;
4840 //pc->print(stderr,pc);
4847 /*-----------------------------------------------------------------*/
4848 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4849 /* pCode chain if they're not used. */
4850 /*-----------------------------------------------------------------*/
4851 void pBlockRemoveUnusedLabels(pBlock *pb)
4853 pCode *pc; pCodeLabel *pcl;
4858 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4860 pBranch *pbr = PCI(pc)->label;
4861 if(pbr && pbr->next) {
4862 pCode *pcd = pb->pcHead;
4864 //fprintf(stderr, "multiple labels\n");
4865 //pc->print(stderr,pc);
4870 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4871 //fprintf(stderr,"Used by:\n");
4872 //pcd->print(stderr,pcd);
4874 exchangeLabels(PCL(pbr->pc),pcd);
4883 for(pc = pb->pcHead; pc; pc = pc->next) {
4885 if(isPCL(pc)) // Label pcode
4887 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4888 pcl = PCL(PCI(pc)->label->pc);
4891 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4893 /* This pCode is a label, so search the pBlock to see if anyone
4896 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4897 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4898 /* Couldn't find an instruction that refers to this label
4899 * So, unlink the pCode label from it's pCode chain
4900 * and destroy the label */
4901 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4903 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4904 if(pc->type == PC_LABEL) {
4906 pCodeLabelDestruct(pc);
4908 unlinkpCodeFromBranch(pc, PCODE(pcl));
4909 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4920 /*-----------------------------------------------------------------*/
4921 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4922 /* chain and put them into pBranches that are */
4923 /* associated with the appropriate pCode */
4925 /*-----------------------------------------------------------------*/
4926 void pBlockMergeLabels(pBlock *pb)
4929 pCode *pc, *pcnext=NULL;
4934 /* First, Try to remove any unused labels */
4935 //pBlockRemoveUnusedLabels(pb);
4937 /* Now loop through the pBlock and merge the labels with the opcodes */
4940 // for(pc = pb->pcHead; pc; pc = pc->next) {
4943 pCode *pcn = pc->next;
4945 if(pc->type == PC_LABEL) {
4947 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4948 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4949 if((pcnext = findNextInstruction(pc) )) {
4951 // Unlink the pCode label from it's pCode chain
4954 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4955 // And link it into the instruction's pBranch labels. (Note, since
4956 // it's possible to have multiple labels associated with one instruction
4957 // we must provide a means to accomodate the additional labels. Thus
4958 // the labels are placed into the singly-linked list "label" as
4959 // opposed to being a single member of the pCodeInstruction.)
4961 //_ALLOC(pbr,sizeof(pBranch));
4962 pbr = Safe_calloc(1,sizeof(pBranch));
4966 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4969 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4971 } else if(pc->type == PC_CSOURCE) {
4973 /* merge the source line symbolic info into the next instruction */
4974 if((pcnext = findNextInstruction(pc) )) {
4976 // Unlink the pCode label from it's pCode chain
4978 PCI(pcnext)->cline = PCCS(pc);
4979 //fprintf(stderr, "merging CSRC\n");
4980 //genericPrint(stderr,pcnext);
4986 pBlockRemoveUnusedLabels(pb);
4990 /*-----------------------------------------------------------------*/
4991 /*-----------------------------------------------------------------*/
4992 int OptimizepCode(char dbName)
4994 #define MAX_PASSES 4
5003 DFPRINTF((stderr," Optimizing pCode\n"));
5007 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5008 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5009 matches += OptimizepBlock(pb);
5012 while(matches && ++passes < MAX_PASSES);
5017 /*-----------------------------------------------------------------*/
5018 /* popCopyGPR2Bit - copy a pcode operator */
5019 /*-----------------------------------------------------------------*/
5021 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5025 pcop = newpCodeOpBit(pc->name, bitval, 0);
5027 if( !( (pcop->type == PO_LABEL) ||
5028 (pcop->type == PO_LITERAL) ||
5029 (pcop->type == PO_STR) ))
5030 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5035 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5037 void pBlockDestruct(pBlock *pb)
5048 /*-----------------------------------------------------------------*/
5049 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5050 /* name dbName and combine them */
5051 /* into one block */
5052 /*-----------------------------------------------------------------*/
5053 void mergepBlocks(char dbName)
5056 pBlock *pb, *pbmerged = NULL,*pbn;
5058 pb = the_pFile->pbHead;
5060 //fprintf(stderr," merging blocks named %c\n",dbName);
5064 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5065 if( getpBlock_dbName(pb) == dbName) {
5067 //fprintf(stderr," merged block %c\n",dbName);
5072 addpCode2pBlock(pbmerged, pb->pcHead);
5073 /* addpCode2pBlock doesn't handle the tail: */
5074 pbmerged->pcTail = pb->pcTail;
5076 pb->prev->next = pbn;
5078 pbn->prev = pb->prev;
5083 //printpBlock(stderr, pbmerged);
5090 /*-----------------------------------------------------------------*/
5091 /* AnalyzeFlow - Examine the flow of the code and optimize */
5093 /* level 0 == minimal optimization */
5094 /* optimize registers that are used only by two instructions */
5095 /* level 1 == maximal optimization */
5096 /* optimize by looking at pairs of instructions that use the */
5098 /*-----------------------------------------------------------------*/
5100 void AnalyzeFlow(int level)
5102 static int times_called=0;
5110 /* if this is not the first time this function has been called,
5111 then clean up old flow information */
5112 if(times_called++) {
5113 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5116 RegsUnMapLiveRanges();
5122 /* Phase 2 - Flow Analysis - Register Banking
5124 * In this phase, the individual flow blocks are examined
5125 * and register banking is fixed.
5128 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5129 //FixRegisterBanking(pb);
5131 /* Phase 2 - Flow Analysis
5133 * In this phase, the pCode is partition into pCodeFlow
5134 * blocks. The flow blocks mark the points where a continuous
5135 * stream of instructions changes flow (e.g. because of
5136 * a call or goto or whatever).
5139 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5143 /* Phase 2 - Flow Analysis - linking flow blocks
5145 * In this phase, the individual flow blocks are examined
5146 * to determine their order of excution.
5149 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5152 /* Phase 3 - Flow Analysis - Flow Tree
5154 * In this phase, the individual flow blocks are examined
5155 * to determine their order of excution.
5158 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5162 /* Phase x - Flow Analysis - Used Banks
5164 * In this phase, the individual flow blocks are examined
5165 * to determine the Register Banks they use
5168 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5172 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5173 pCodeRegMapLiveRanges(pb);
5175 RemoveUnusedRegisters();
5177 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5178 pCodeRegOptimizeRegUsage(level);
5183 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5188 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5190 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5191 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5192 pcflow = pcflow->next) {
5194 FillFlow(PCFL(pcflow));
5199 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5201 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5202 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5203 pcflow = pcflow->next) {
5205 FlowStats(PCFL(pcflow));
5211 /*-----------------------------------------------------------------*/
5212 /* AnalyzeBanking - Called after the memory addresses have been */
5213 /* assigned to the registers. */
5215 /*-----------------------------------------------------------------*/
5217 void AnalyzeBanking(void)
5221 if(!picIsInitialized()) {
5222 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5226 if (!the_pFile) return;
5228 /* Phase x - Flow Analysis - Used Banks
5230 * In this phase, the individual flow blocks are examined
5231 * to determine the Register Banks they use
5237 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5238 // BanksUsedFlow(pb);
5239 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5240 FixRegisterBanking(pb);
5247 /*-----------------------------------------------------------------*/
5248 /*-----------------------------------------------------------------*/
5249 DEFSETFUNC (resetrIdx)
5251 regs *r = (regs *)item;
5259 /*-----------------------------------------------------------------*/
5260 /* InitRegReuse - Initialises variables for code analyzer */
5261 /*-----------------------------------------------------------------*/
5262 void InitReuseReg(void)
5264 /* Find end of statically allocated variables for start idx */
5265 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5266 /* XXX: Avoid clashes with fixed registers, start late. */
5267 unsigned maxIdx = 0x1000;
5269 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5270 if (r->type != REG_SFR) {
5271 maxIdx += r->size; /* Increment for all statically allocated variables */
5275 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5278 /*-----------------------------------------------------------------*/
5279 /*-----------------------------------------------------------------*/
5280 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
5284 /* check recursion */
5285 pc = setFirstItem(pb->function_entries);
5290 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5296 DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
5298 if (pb->tregisters) {
5300 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5301 if (r->type == REG_GPR) {
5303 if (r->rIdx < (int)idx) {
5306 // make sure, idx is not yet used in this routine...
5308 regset = pb->tregisters;
5309 // do not touch s->curr ==> outer loop!
5310 while (regset && ((regs *)regset->item)->rIdx != idx) {
5311 regset = regset->next;
5316 if (peakIdx < idx) peakIdx = idx;
5317 sprintf(s,"r0x%02X", r->rIdx);
5318 DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
5320 r->name = Safe_strdup(s);
5326 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5328 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5329 char *dest = get_op_from_instruction(PCI(pc));
5331 pCode *pcn = findFunction(dest);
5333 /* This index increment from subroutines is not required, as all subroutines
5334 * may share registers NOT used by this one (< idx).
5335 * BUT if called functions A and B share a register, which gets assigned
5336 * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
5338 * As an alternative to this "solution" we could check above whether an
5339 * to-be-assigned rIdx is already present in the register set of the
5340 * current function. This would increase the reused registers and make this
5341 * `idx =' irrelevant.
5342 * UPDATE: Implemented above; not fast, but works.
5343 * (Problem shown with regression test src/regression/sub2.c)
5345 /*idx = */register_reassign(pcn->pb,idx,level+1);
5353 /*------------------------------------------------------------------*/
5354 /* ReuseReg were call tree permits */
5356 /* Re-allocate the GPR for optimum reuse for a given pblock */
5357 /* eg if a function m() calls function f1() and f2(), where f1 */
5358 /* allocates a local variable vf1 and f2 allocates a local */
5359 /* variable vf2. Then providing f1 and f2 do not call each other */
5360 /* they may share the same general purpose registers for vf1 and */
5362 /* This is done by first setting the the regs rIdx to start after */
5363 /* all the global variables, then walking through the call tree */
5364 /* renaming the registers to match their new idx and incrementng */
5365 /* it as it goes. If a function has already been called it will */
5366 /* only rename the registers if it has already used up those */
5367 /* registers ie rIdx of the function's registers is lower than the */
5368 /* current rIdx. That way the register will not be reused while */
5369 /* still being used by an eariler function call. */
5371 /* Note for this to work the functions need to be declared static. */
5373 /*------------------------------------------------------------------*/
5377 if (!the_pFile) return;
5379 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5380 /* Non static functions can be called from other modules so their registers must reassign */
5381 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5382 register_reassign(pb,peakIdx,0);
5386 /*-----------------------------------------------------------------*/
5387 /* buildCallTree - look at the flow and extract all of the calls */
5389 /*-----------------------------------------------------------------*/
5391 void buildCallTree(void )
5400 /* Now build the call tree.
5401 First we examine all of the pCodes for functions.
5402 Keep in mind that the function boundaries coincide
5403 with pBlock boundaries.
5405 The algorithm goes something like this:
5406 We have two nested loops. The outer loop iterates
5407 through all of the pBlocks/functions. The inner
5408 loop iterates through all of the pCodes for
5409 a given pBlock. When we begin iterating through
5410 a pBlock, the variable pc_fstart, pCode of the start
5411 of a function, is cleared. We then search for pCodes
5412 of type PC_FUNCTION. When one is encountered, we
5413 initialize pc_fstart to this and at the same time
5414 associate a new pBranch object that signifies a
5415 branch entry. If a return is found, then this signifies
5416 a function exit point. We'll link the pCodes of these
5417 returns to the matching pc_fstart.
5419 When we're done, a doubly linked list of pBranches
5420 will exist. The head of this list is stored in
5421 `the_pFile', which is the meta structure for all
5422 of the pCode. Look at the printCallTree function
5423 on how the pBranches are linked together.
5426 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5427 pCode *pc_fstart=NULL;
5428 for(pc = pb->pcHead; pc; pc = pc->next) {
5430 pCodeFunction *pcf = PCF(pc);
5433 if(STRCASECMP(pcf->fname, "_main") == 0) {
5434 //fprintf(stderr," found main \n");
5435 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5439 pbr = Safe_calloc(1,sizeof(pBranch));
5440 pbr->pc = pc_fstart = pc;
5443 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5445 // Here's a better way of doing the same:
5446 addSet(&pb->function_entries, pc);
5449 // Found an exit point in a function, e.g. return
5450 // (Note, there may be more than one return per function)
5452 pBranchLink(PCF(pc_fstart), pcf);
5454 addSet(&pb->function_exits, pc);
5456 } else if(isCALL(pc)) {
5457 addSet(&pb->function_calls,pc);
5463 /*-----------------------------------------------------------------*/
5464 /* AnalyzepCode - parse the pCode that has been generated and form */
5465 /* all of the logical connections. */
5467 /* Essentially what's done here is that the pCode flow is */
5469 /*-----------------------------------------------------------------*/
5471 void AnalyzepCode(char dbName)
5482 /* Phase 1 - Register allocation and peep hole optimization
5484 * The first part of the analysis is to determine the registers
5485 * that are used in the pCode. Once that is done, the peep rules
5486 * are applied to the code. We continue to loop until no more
5487 * peep rule optimizations are found (or until we exceed the
5488 * MAX_PASSES threshold).
5490 * When done, the required registers will be determined.
5496 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5498 /* First, merge the labels with the instructions */
5499 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5500 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5502 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5503 pBlockMergeLabels(pb);
5506 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5510 changes = OptimizepCode(dbName);
5512 } while(changes && (i++ < MAX_PASSES));
5517 /*-----------------------------------------------------------------*/
5518 /* ispCodeFunction - returns true if *pc is the pCode of a */
5520 /*-----------------------------------------------------------------*/
5521 bool ispCodeFunction(pCode *pc)
5524 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5530 /*-----------------------------------------------------------------*/
5531 /* findFunction - Search for a function by name (given the name) */
5532 /* in the set of all functions that are in a pBlock */
5533 /* (note - I expect this to change because I'm planning to limit */
5534 /* pBlock's to just one function declaration */
5535 /*-----------------------------------------------------------------*/
5536 pCode *findFunction(char *fname)
5543 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5545 pc = setFirstItem(pb->function_entries);
5548 if((pc->type == PC_FUNCTION) &&
5550 (strcmp(fname, PCF(pc)->fname)==0))
5553 pc = setNextItem(pb->function_entries);
5561 void MarkUsedRegisters(set *regset)
5566 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5567 r2 = pic14_regWithIdx(r1->rIdx);
5575 void pBlockStats(FILE *of, pBlock *pb)
5581 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5583 // for now just print the first element of each set
5584 pc = setFirstItem(pb->function_entries);
5586 fprintf(of,";entry: ");
5589 pc = setFirstItem(pb->function_exits);
5591 fprintf(of,";has an exit\n");
5595 pc = setFirstItem(pb->function_calls);
5597 fprintf(of,";functions called:\n");
5600 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5601 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5603 pc = setNextItem(pb->function_calls);
5607 r = setFirstItem(pb->tregisters);
5609 int n = elementsInSet(pb->tregisters);
5611 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5614 fprintf(of,"; %s\n",r->name);
5615 r = setNextItem(pb->tregisters);
5620 /*-----------------------------------------------------------------*/
5621 /*-----------------------------------------------------------------*/
5623 static void sequencepCode(void)
5629 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5631 pb->seq = GpCodeSequenceNumber+1;
5633 for( pc = pb->pcHead; pc; pc = pc->next)
5634 pc->seq = ++GpCodeSequenceNumber;
5640 /*-----------------------------------------------------------------*/
5641 /*-----------------------------------------------------------------*/
5643 set *register_usage(pBlock *pb)
5646 set *registers=NULL;
5647 set *registersInCallPath = NULL;
5649 / * check recursion * /
5651 pc = setFirstItem(pb->function_entries);
5658 if(pc->type != PC_FUNCTION)
5659 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5661 pc = setFirstItem(pb->function_calls);
5662 for( ; pc; pc = setNextItem(pb->function_calls)) {
5664 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5665 char *dest = get_op_from_instruction(PCI(pc));
5667 pcn = findFunction(dest);
5669 registersInCallPath = register_usage(pcn->pb);
5671 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5676 pBlockStats(stderr,pb); // debug
5679 // Mark the registers in this block as used.
5681 MarkUsedRegisters(pb->tregisters);
5682 if(registersInCallPath) {
5683 / * registers were used in the functions this pBlock has called * /
5684 / * so now, we need to see if these collide with the ones we are * /
5687 regs *r1,*r2, *newreg;
5689 DFPRINTF((stderr,"comparing registers\n"));
5691 r1 = setFirstItem(registersInCallPath);
5693 if (r1->type != REG_STK) {
5694 r2 = setFirstItem(pb->tregisters);
5696 while(r2 && (r2->type != REG_STK)) {
5698 if(r2->rIdx == r1->rIdx) {
5699 newreg = pic14_findFreeReg(REG_GPR);
5703 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5707 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5708 r1->rIdx, newreg->rIdx));
5709 r2->rIdx = newreg->rIdx;
5711 r2->name = Safe_strdup(newreg->name);
5715 newreg->wasUsed = 1;
5717 r2 = setNextItem(pb->tregisters);
5721 r1 = setNextItem(registersInCallPath);
5724 / * Collisions have been resolved. Now free the registers in the call path * /
5725 r1 = setFirstItem(registersInCallPath);
5727 newreg = pic14_regWithIdx(r1->rIdx);
5728 if (newreg) newreg->isFree = 1;
5729 r1 = setNextItem(registersInCallPath);
5733 // MarkUsedRegisters(pb->registers);
5735 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5738 DFPRINTF((stderr,"returning regs\n"));
5740 DFPRINTF((stderr,"not returning regs\n"));
5742 DFPRINTF((stderr,"pBlock after register optim.\n"));
5743 pBlockStats(stderr,pb); // debug
5750 /*-----------------------------------------------------------------*/
5751 /* printCallTree - writes the call tree to a file */
5753 /*-----------------------------------------------------------------*/
5754 void pct2(FILE *of,pBlock *pb,int indent)
5758 // set *registersInCallPath = NULL;
5764 return; //recursion ?
5766 pc = setFirstItem(pb->function_entries);
5773 for(i=0;i<indent;i++) // Indentation
5776 if(pc->type == PC_FUNCTION)
5777 fprintf(of,"%s\n",PCF(pc)->fname);
5782 pc = setFirstItem(pb->function_calls);
5783 for( ; pc; pc = setNextItem(pb->function_calls)) {
5785 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5786 char *dest = get_op_from_instruction(PCI(pc));
5788 pcn = findFunction(dest);
5790 pct2(of,pcn->pb,indent+1);
5792 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5800 /*-----------------------------------------------------------------*/
5801 /* printCallTree - writes the call tree to a file */
5803 /*-----------------------------------------------------------------*/
5805 void printCallTree(FILE *of)
5817 fprintf(of, "\npBlock statistics\n");
5818 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5823 fprintf(of,"Call Tree\n");
5824 pbr = the_pFile->functions;
5828 if(!ispCodeFunction(pc))
5829 fprintf(of,"bug in call tree");
5832 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5834 while(pc->next && !ispCodeFunction(pc->next)) {
5836 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5837 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5845 fprintf(of,"\n**************\n\na better call tree\n");
5846 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5851 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5852 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5858 /*-----------------------------------------------------------------*/
5860 /*-----------------------------------------------------------------*/
5862 void InlineFunction(pBlock *pb)
5870 pc = setFirstItem(pb->function_calls);
5872 for( ; pc; pc = setNextItem(pb->function_calls)) {
5875 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5876 pCode *pcp = pc->prev;
5882 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 */
5884 InlineFunction(pcn->pb);
5887 At this point, *pc points to a CALL mnemonic, and
5888 *pcn points to the function that is being called.
5890 To in-line this call, we need to remove the CALL
5891 and RETURN(s), and link the function pCode in with
5898 /* Check if previous instruction was a bit skip */
5899 if (isPCI_BITSKIP(pcp)) {
5901 /* Invert skip instruction and add a goto */
5902 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5904 if(isPCL(pc_call->next)) { // Label pcode
5905 pcl = PCL(pc_call->next);
5906 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5907 pcl = PCL(PCI(pc_call->next)->label->pc);
5909 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5910 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5912 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5915 /* remove callee pBlock from the pBlock linked list */
5916 removepBlock(pcn->pb);
5924 /* Remove the Function pCode */
5925 pct = findNextInstruction(pcn->next);
5927 /* Link the function with the callee */
5928 if (pcp) pcp->next = pcn->next;
5929 pcn->next->prev = pcp;
5931 /* Convert the function name into a label */
5933 pbr = Safe_calloc(1,sizeof(pBranch));
5934 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5936 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5937 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5939 /* turn all of the return's except the last into goto's */
5940 /* check case for 2 instruction pBlocks */
5941 pce = findNextInstruction(pcn->next);
5943 pCode *pce_next = findNextInstruction(pce->next);
5945 if(pce_next == NULL) {
5946 /* found the last return */
5947 pCode *pc_call_next = findNextInstruction(pc_call->next);
5949 //fprintf(stderr,"found last return\n");
5950 //pce->print(stderr,pce);
5951 pce->prev->next = pc_call->next;
5952 pc_call->next->prev = pce->prev;
5953 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5962 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5968 /*-----------------------------------------------------------------*/
5970 /*-----------------------------------------------------------------*/
5972 void InlinepCode(void)
5981 if(!functionInlining)
5984 /* Loop through all of the function definitions and count the
5985 * number of times each one is called */
5986 //fprintf(stderr,"inlining %d\n",__LINE__);
5988 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5990 pc = setFirstItem(pb->function_calls);
5992 for( ; pc; pc = setNextItem(pb->function_calls)) {
5995 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5996 if(pcn && isPCF(pcn)) {
5997 PCF(pcn)->ncalled++;
6000 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6005 //fprintf(stderr,"inlining %d\n",__LINE__);
6007 /* Now, Loop through the function definitions again, but this
6008 * time inline those functions that have only been called once. */
6010 InlineFunction(the_pFile->pbHead);
6011 //fprintf(stderr,"inlining %d\n",__LINE__);
6013 for(pb = the_pFile->pbHead; pb; pb = pb->next)