1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
39 #define STRCASECMP strcasecmp
42 /****************************************************************/
43 /****************************************************************/
45 peepCommand peepCommands[] = {
47 {NOTBITSKIP, "_NOTBITSKIP_"},
48 {BITSKIP, "_BITSKIP_"},
49 {INVERTBITSKIP, "_INVERTBITSKIP_"},
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
64 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
74 static 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 peepOptimizing = 1; /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1; /* inline functions if nonzero */
80 int debug_verbose = 0; /* Set true to inundate .asm file */
82 // static int GpCodeSequenceNumber = 1;
85 /* statistics (code size estimation) */
86 static unsigned int pcode_insns = 0;
87 static unsigned int pcode_doubles = 0;
90 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
91 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
93 extern void RemoveUnusedRegisters(void);
94 extern void RegsUnMapLiveRanges(void);
95 extern void BuildFlowTree(pBlock *pb);
96 extern void pCodeRegOptimizeRegUsage(int level);
97 extern int picIsInitialized(void);
98 extern const char *pCodeOpType(pCodeOp *pcop);
100 /****************************************************************/
101 /* Forward declarations */
102 /****************************************************************/
104 void unlinkpCode(pCode *pc);
106 static void genericAnalyze(pCode *pc);
107 static void AnalyzeGOTO(pCode *pc);
108 static void AnalyzeSKIP(pCode *pc);
109 static void AnalyzeRETURN(pCode *pc);
112 static void genericDestruct(pCode *pc);
113 static void genericPrint(FILE *of,pCode *pc);
115 static void pCodePrintLabel(FILE *of, pCode *pc);
116 static void pCodePrintFunction(FILE *of, pCode *pc);
117 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
118 static char *get_op_from_instruction( pCodeInstruction *pcc);
119 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
120 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
121 int pCodePeepMatchRule(pCode *pc);
122 void pBlockStats(FILE *of, pBlock *pb);
123 pBlock *newpBlock(void);
124 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
125 void pCodeRegMapLiveRanges(pBlock *pb);
128 /****************************************************************/
129 /* PIC Instructions */
130 /****************************************************************/
132 pCodeInstruction pciADDWF = {
133 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
146 1,0, // dest, bit instruction
148 0, // literal operand
150 (PCC_W | PCC_REGISTER), // inCond
151 (PCC_REGISTER | PCC_Z) // outCond
154 pCodeInstruction pciADDFW = {
155 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
168 0,0, // dest, bit instruction
170 0, // literal operand
172 (PCC_W | PCC_REGISTER), // inCond
173 (PCC_W | PCC_Z) // outCond
176 pCodeInstruction pciADDLW = {
177 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
190 0,0, // dest, bit instruction
192 1, // literal operand
194 (PCC_W | PCC_LITERAL), // inCond
195 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
198 pCodeInstruction pciANDLW = {
199 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
212 0,0, // dest, bit instruction
214 1, // literal operand
216 (PCC_W | PCC_LITERAL), // inCond
217 (PCC_W | PCC_Z) // outCond
220 pCodeInstruction pciANDWF = {
221 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
234 1,0, // dest, bit instruction
236 0, // literal operand
238 (PCC_W | PCC_REGISTER), // inCond
239 (PCC_REGISTER | PCC_Z) // outCond
242 pCodeInstruction pciANDFW = {
243 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
256 0,0, // dest, bit instruction
258 0, // literal operand
260 (PCC_W | PCC_REGISTER), // inCond
261 (PCC_W | PCC_Z) // outCond
264 pCodeInstruction pciBCF = {
265 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
278 1,1, // dest, bit instruction
280 0, // literal operand
282 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
283 PCC_REGISTER // outCond
286 pCodeInstruction pciBSF = {
287 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
300 1,1, // dest, bit instruction
302 0, // literal operand
304 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
305 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
308 pCodeInstruction pciBTFSC = {
309 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
322 0,1, // dest, bit instruction
324 0, // literal operand
326 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
327 PCC_EXAMINE_PCOP // outCond
330 pCodeInstruction pciBTFSS = {
331 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
344 0,1, // dest, bit instruction
346 0, // literal operand
348 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
349 PCC_EXAMINE_PCOP // outCond
352 pCodeInstruction pciCALL = {
353 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
366 0,0, // dest, bit instruction
368 0, // literal operand
374 pCodeInstruction pciCOMF = {
375 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
388 1,0, // dest, bit instruction
390 0, // literal operand
392 PCC_REGISTER, // inCond
393 PCC_REGISTER // outCond
396 pCodeInstruction pciCOMFW = {
397 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
410 0,0, // dest, bit instruction
412 0, // literal operand
414 PCC_REGISTER, // inCond
418 pCodeInstruction pciCLRF = {
419 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
432 0,0, // dest, bit instruction
434 0, // literal operand
437 PCC_REGISTER // outCond
440 pCodeInstruction pciCLRW = {
441 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
454 0,0, // dest, bit instruction
456 0, // literal operand
462 pCodeInstruction pciCLRWDT = {
463 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
476 0,0, // dest, bit instruction
478 0, // literal operand
484 pCodeInstruction pciDECF = {
485 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
498 1,0, // dest, bit instruction
500 0, // literal operand
502 PCC_REGISTER, // inCond
503 PCC_REGISTER // outCond
506 pCodeInstruction pciDECFW = {
507 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
520 0,0, // dest, bit instruction
522 0, // literal operand
524 PCC_REGISTER, // inCond
528 pCodeInstruction pciDECFSZ = {
529 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
542 1,0, // dest, bit instruction
544 0, // literal operand
546 PCC_REGISTER, // inCond
547 PCC_REGISTER // outCond
550 pCodeInstruction pciDECFSZW = {
551 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
564 0,0, // dest, bit instruction
566 0, // literal operand
568 PCC_REGISTER, // inCond
572 pCodeInstruction pciGOTO = {
573 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
586 0,0, // dest, bit instruction
588 0, // literal operand
594 pCodeInstruction pciINCF = {
595 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
608 1,0, // dest, bit instruction
610 0, // literal operand
612 PCC_REGISTER, // inCond
613 PCC_REGISTER // outCond
616 pCodeInstruction pciINCFW = {
617 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
630 0,0, // dest, bit instruction
632 0, // literal operand
634 PCC_REGISTER, // inCond
638 pCodeInstruction pciINCFSZ = {
639 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
652 1,0, // dest, bit instruction
654 0, // literal operand
656 PCC_REGISTER, // inCond
657 PCC_REGISTER // outCond
660 pCodeInstruction pciINCFSZW = {
661 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
674 0,0, // dest, bit instruction
676 0, // literal operand
678 PCC_REGISTER, // inCond
682 pCodeInstruction pciIORWF = {
683 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
696 1,0, // dest, bit instruction
698 0, // literal operand
700 (PCC_W | PCC_REGISTER), // inCond
701 (PCC_REGISTER | PCC_Z) // outCond
704 pCodeInstruction pciIORFW = {
705 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
718 0,0, // dest, bit instruction
720 0, // literal operand
722 (PCC_W | PCC_REGISTER), // inCond
723 (PCC_W | PCC_Z) // outCond
726 pCodeInstruction pciIORLW = {
727 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
740 0,0, // dest, bit instruction
742 1, // literal operand
744 (PCC_W | PCC_LITERAL), // inCond
745 (PCC_W | PCC_Z) // outCond
748 pCodeInstruction pciMOVF = {
749 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
762 1,0, // dest, bit instruction
764 0, // literal operand
766 PCC_REGISTER, // inCond
770 pCodeInstruction pciMOVFW = {
771 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
784 0,0, // dest, bit instruction
786 0, // literal operand
788 PCC_REGISTER, // inCond
789 (PCC_W | PCC_Z) // outCond
792 pCodeInstruction pciMOVWF = {
793 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
806 0,0, // dest, bit instruction
808 0, // literal operand
811 PCC_REGISTER // outCond
814 pCodeInstruction pciMOVLW = {
815 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
827 0,0, // dest, bit instruction
829 1, // literal operand
831 (PCC_NONE | PCC_LITERAL), // inCond
835 pCodeInstruction pciNOP = {
836 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
848 0,0, // dest, bit instruction
850 0, // literal operand
856 pCodeInstruction pciRETFIE = {
857 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
870 0,0, // dest, bit instruction
872 0, // literal operand
875 PCC_NONE // outCond (not true... affects the GIE bit too)
878 pCodeInstruction pciRETLW = {
879 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
892 0,0, // dest, bit instruction
894 1, // literal operand
896 PCC_LITERAL, // inCond
900 pCodeInstruction pciRETURN = {
901 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
914 0,0, // dest, bit instruction
916 0, // literal operand
922 pCodeInstruction pciRLF = {
923 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
936 1,0, // dest, bit instruction
938 0, // literal operand
940 (PCC_C | PCC_REGISTER), // inCond
941 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
944 pCodeInstruction pciRLFW = {
945 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
958 0,0, // dest, bit instruction
960 0, // literal operand
962 (PCC_C | PCC_REGISTER), // inCond
963 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
966 pCodeInstruction pciRRF = {
967 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
980 1,0, // dest, bit instruction
982 0, // literal operand
984 (PCC_C | PCC_REGISTER), // inCond
985 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
988 pCodeInstruction pciRRFW = {
989 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1002 0,0, // dest, bit instruction
1003 0,0, // branch, skip
1004 0, // literal operand
1006 (PCC_C | PCC_REGISTER), // inCond
1007 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1010 pCodeInstruction pciSUBWF = {
1011 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1017 NULL, // from branch
1024 1,0, // dest, bit instruction
1025 0,0, // branch, skip
1026 0, // literal operand
1028 (PCC_W | PCC_REGISTER), // inCond
1029 (PCC_REGISTER | PCC_Z) // outCond
1032 pCodeInstruction pciSUBFW = {
1033 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1039 NULL, // from branch
1046 0,0, // dest, bit instruction
1047 0,0, // branch, skip
1048 0, // literal operand
1050 (PCC_W | PCC_REGISTER), // inCond
1051 (PCC_W | PCC_Z) // outCond
1054 pCodeInstruction pciSUBLW = {
1055 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1061 NULL, // from branch
1068 0,0, // dest, bit instruction
1069 0,0, // branch, skip
1070 1, // literal operand
1072 (PCC_W | PCC_LITERAL), // inCond
1073 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1076 pCodeInstruction pciSWAPF = {
1077 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1083 NULL, // from branch
1090 1,0, // dest, bit instruction
1091 0,0, // branch, skip
1092 0, // literal operand
1094 (PCC_REGISTER), // inCond
1095 (PCC_REGISTER) // outCond
1098 pCodeInstruction pciSWAPFW = {
1099 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1105 NULL, // from branch
1112 0,0, // dest, bit instruction
1113 0,0, // branch, skip
1114 0, // literal operand
1116 (PCC_REGISTER), // inCond
1120 pCodeInstruction pciTRIS = {
1121 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1127 NULL, // from branch
1134 0,0, // dest, bit instruction
1135 0,0, // branch, skip
1136 0, // literal operand
1139 PCC_REGISTER // outCond
1142 pCodeInstruction pciXORWF = {
1143 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1149 NULL, // from branch
1156 1,0, // dest, bit instruction
1157 0,0, // branch, skip
1158 0, // literal operand
1160 (PCC_W | PCC_REGISTER), // inCond
1161 (PCC_REGISTER | PCC_Z) // outCond
1164 pCodeInstruction pciXORFW = {
1165 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1171 NULL, // from branch
1178 0,0, // dest, bit instruction
1179 0,0, // branch, skip
1180 0, // literal operand
1182 (PCC_W | PCC_REGISTER), // inCond
1183 (PCC_W | PCC_Z) // outCond
1186 pCodeInstruction pciXORLW = {
1187 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1193 NULL, // from branch
1200 0,0, // dest, bit instruction
1201 0,0, // branch, skip
1202 1, // literal operand
1204 (PCC_W | PCC_LITERAL), // inCond
1205 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1209 pCodeInstruction pciBANKSEL = {
1210 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1216 NULL, // from branch
1223 0,0, // dest, bit instruction
1224 0,0, // branch, skip
1225 0, // literal operand
1228 PCC_REGISTER // outCond
1231 pCodeInstruction pciPAGESEL = {
1232 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1238 NULL, // from branch
1245 0,0, // dest, bit instruction
1246 0,0, // branch, skip
1247 0, // literal operand
1250 PCC_REGISTER // outCond
1253 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1256 /*-----------------------------------------------------------------*/
1257 /* return a unique ID number to assist pCodes debuging */
1258 /*-----------------------------------------------------------------*/
1259 unsigned PCodeID(void) {
1260 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1262 static unsigned int stop;
1263 if (pcodeId == 1448)
1264 stop++; // Place break point here
1269 #ifdef HAVE_VSNPRINTF
1270 // Alas, vsnprintf is not ANSI standard, and does not exist
1271 // on Solaris (and probably other non-Gnu flavored Unixes).
1273 /*-----------------------------------------------------------------*/
1274 /* SAFE_snprintf - like snprintf except the string pointer is */
1275 /* after the string has been printed to. This is */
1276 /* useful for printing to string as though if it */
1277 /* were a stream. */
1278 /*-----------------------------------------------------------------*/
1279 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1287 va_start(val, format);
1289 vsnprintf(*str, *size, format, val);
1294 if((size_t)len > *size) {
1295 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1296 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1304 #else // HAVE_VSNPRINTF
1306 // This version is *not* safe, despite the name.
1308 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1312 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1317 va_start(val, format);
1319 vsprintf(buffer, format, val);
1322 len = strlen(buffer);
1324 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1325 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1328 strcpy(*str, buffer);
1334 #endif // HAVE_VSNPRINTF
1337 extern void initStack(int base_address, int size);
1338 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1339 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1340 extern void init_pic(char *);
1342 void pCodeInitRegisters(void)
1344 static int initialized=0;
1345 int shareBankAddress,stkSize;
1351 init_pic(port->processor);
1352 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1353 if ((unsigned)shareBankAddress > getMaxRam()) /* If total RAM is less than 0x7f as with 16f84 then reduce shareBankAddress to fit */
1354 shareBankAddress = (int)getMaxRam();
1355 stkSize = 15; /* Set pseudo stack size to 15, on multi memory bank ICs this leaves room for WSAVE (used for interrupts) to fit into the shared portion of the memory bank */
1356 initStack(shareBankAddress, stkSize); /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1358 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1359 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1360 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1361 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1362 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1363 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1365 pc_status.rIdx = IDX_STATUS;
1366 pc_fsr.rIdx = IDX_FSR;
1367 pc_indf.rIdx = IDX_INDF;
1368 pc_intcon.rIdx = IDX_INTCON;
1369 pc_pcl.rIdx = IDX_PCL;
1370 pc_pclath.rIdx = IDX_PCLATH;
1372 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1373 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1374 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1376 pc_wsave.rIdx = pc_wsave.r->rIdx;
1377 pc_ssave.rIdx = pc_ssave.r->rIdx;
1378 pc_psave.rIdx = pc_psave.r->rIdx;
1380 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1381 pc_wsave.r->address = shareBankAddress-stkSize;
1382 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1383 pc_ssave.r->address = shareBankAddress-stkSize-1;
1384 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1385 pc_psave.r->address = shareBankAddress-stkSize-2;
1387 /* probably should put this in a separate initialization routine */
1388 pb_dead_pcodes = newpBlock();
1392 /*-----------------------------------------------------------------*/
1393 /* mnem2key - convert a pic mnemonic into a hash key */
1394 /* (BTW - this spreads the mnemonics quite well) */
1396 /*-----------------------------------------------------------------*/
1398 int mnem2key(char const *mnem)
1407 key += toupper(*mnem++) +1;
1411 return (key & 0x1f);
1415 void pic14initMnemonics(void)
1420 pCodeInstruction *pci;
1422 if(mnemonics_initialized)
1425 //FIXME - probably should NULL out the array before making the assignments
1426 //since we check the array contents below this initialization.
1428 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1429 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1430 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1431 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1432 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1433 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1434 pic14Mnemonics[POC_BCF] = &pciBCF;
1435 pic14Mnemonics[POC_BSF] = &pciBSF;
1436 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1437 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1438 pic14Mnemonics[POC_CALL] = &pciCALL;
1439 pic14Mnemonics[POC_COMF] = &pciCOMF;
1440 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1441 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1442 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1443 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1444 pic14Mnemonics[POC_DECF] = &pciDECF;
1445 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1446 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1447 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1448 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1449 pic14Mnemonics[POC_INCF] = &pciINCF;
1450 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1451 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1452 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1453 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1454 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1455 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1456 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1457 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1458 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1459 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1460 pic14Mnemonics[POC_NOP] = &pciNOP;
1461 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1462 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1463 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1464 pic14Mnemonics[POC_RLF] = &pciRLF;
1465 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1466 pic14Mnemonics[POC_RRF] = &pciRRF;
1467 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1468 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1469 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1470 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1471 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1472 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1473 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1474 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1475 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1476 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1477 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1478 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1480 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1481 if(pic14Mnemonics[i])
1482 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1483 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1486 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1487 pci = hTabNextItem(pic14MnemonicsHash, &key);
1490 mnemonics_initialized = 1;
1493 int getpCodePeepCommand(char *cmd);
1495 int getpCode(char *mnem,unsigned dest)
1498 pCodeInstruction *pci;
1499 int key = mnem2key(mnem);
1501 if(!mnemonics_initialized)
1502 pic14initMnemonics();
1504 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1508 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1509 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1513 pci = hTabNextItemWK (pic14MnemonicsHash);
1520 /*-----------------------------------------------------------------*
1521 * pic14initpCodePeepCommands
1523 *-----------------------------------------------------------------*/
1524 void pic14initpCodePeepCommands(void)
1532 hTabAddItem(&pic14pCodePeepCommandsHash,
1533 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1535 } while (peepCommands[i].cmd);
1537 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1540 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1541 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1546 /*-----------------------------------------------------------------
1549 *-----------------------------------------------------------------*/
1551 int getpCodePeepCommand(char *cmd)
1555 int key = mnem2key(cmd);
1558 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1561 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1562 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1566 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1573 char getpBlock_dbName(pBlock *pb)
1579 return pb->cmemmap->dbName;
1583 void pBlockConvert2ISR(pBlock *pb)
1594 /*-----------------------------------------------------------------*/
1595 /* movepBlock2Head - given the dbname of a pBlock, move all */
1596 /* instances to the front of the doubly linked */
1597 /* list of pBlocks */
1598 /*-----------------------------------------------------------------*/
1600 void movepBlock2Head(char dbName)
1607 pb = the_pFile->pbHead;
1611 if(getpBlock_dbName(pb) == dbName) {
1612 pBlock *pbn = pb->next;
1613 pb->next = the_pFile->pbHead;
1614 the_pFile->pbHead->prev = pb;
1615 the_pFile->pbHead = pb;
1618 pb->prev->next = pbn;
1620 // If the pBlock that we just moved was the last
1621 // one in the link of all of the pBlocks, then we
1622 // need to point the tail to the block just before
1623 // the one we moved.
1624 // Note: if pb->next is NULL, then pb must have
1625 // been the last pBlock in the chain.
1628 pbn->prev = pb->prev;
1630 the_pFile->pbTail = pb->prev;
1641 void copypCode(FILE *of, char dbName)
1645 if(!of || !the_pFile)
1648 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1649 if(getpBlock_dbName(pb) == dbName) {
1658 void resetpCodeStatistics (void)
1660 pcode_insns = pcode_doubles = 0;
1663 void dumppCodeStatistics (FILE *of)
1665 /* dump statistics */
1667 fprintf (of, ";\tcode size estimation:\n");
1668 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1672 void pcode_test(void)
1675 DFPRINTF((stderr,"pcode is alive!\n"));
1685 /* create the file name */
1686 strcpy(buffer,dstFileName);
1687 strcat(buffer,".p");
1689 if( !(pFile = fopen(buffer, "w" ))) {
1690 werror(E_FILE_OPEN_ERR,buffer);
1694 fprintf(pFile,"pcode dump\n\n");
1696 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1697 fprintf(pFile,"\n\tNew pBlock\n\n");
1699 fprintf(pFile,"%s",pb->cmemmap->sname);
1701 fprintf(pFile,"internal pblock");
1703 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1704 printpBlock(pFile,pb);
1708 /*-----------------------------------------------------------------*/
1709 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1710 /* ister, RegCond will return the bit being referenced. */
1712 /* fixme - why not just OR in the pcop bit field */
1713 /*-----------------------------------------------------------------*/
1715 static int RegCond(pCodeOp *pcop)
1721 if (pcop->type == PO_GPR_BIT) {
1722 char *name = pcop->name;
1724 name = PCOR(pcop)->r->name;
1725 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1726 switch(PCORB(pcop)->bit) {
1740 /*-----------------------------------------------------------------*/
1741 /* newpCode - create and return a newly initialized pCode */
1743 /* fixme - rename this */
1745 /* The purpose of this routine is to create a new Instruction */
1746 /* pCode. This is called by gen.c while the assembly code is being */
1750 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1751 /* (note that the op is analogous to but not the */
1752 /* same thing as the opcode of the instruction.) */
1753 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1756 /* a pointer to the new malloc'd pCode is returned. */
1760 /*-----------------------------------------------------------------*/
1761 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1763 pCodeInstruction *pci ;
1765 if(!mnemonics_initialized)
1766 pic14initMnemonics();
1768 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1770 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1771 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1772 pci->pc.id = PCodeID();
1775 if(pci->inCond & PCC_EXAMINE_PCOP)
1776 pci->inCond |= RegCond(pcop);
1778 if(pci->outCond & PCC_EXAMINE_PCOP)
1779 pci->outCond |= RegCond(pcop);
1781 pci->pc.prev = pci->pc.next = NULL;
1782 return (pCode *)pci;
1785 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1791 /*-----------------------------------------------------------------*/
1792 /* newpCodeWild - create a "wild" as in wild card pCode */
1794 /* Wild pcodes are used during the peep hole optimizer to serve */
1795 /* as place holders for any instruction. When a snippet of code is */
1796 /* compared to a peep hole rule, the wild card opcode will match */
1797 /* any instruction. However, the optional operand and label are */
1798 /* additional qualifiers that must also be matched before the */
1799 /* line (of assembly code) is declared matched. Note that the */
1800 /* operand may be wild too. */
1802 /* Note, a wild instruction is specified just like a wild var: */
1803 /* %4 ; A wild instruction, */
1804 /* See the peeph.def file for additional examples */
1806 /*-----------------------------------------------------------------*/
1808 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1813 pcw = Safe_calloc(1,sizeof(pCodeWild));
1815 pcw->pci.pc.type = PC_WILD;
1816 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1817 pcw->id = PCodeID();
1818 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1819 pcw->pci.pc.pb = NULL;
1821 // pcw->pci.pc.analyze = genericAnalyze;
1822 pcw->pci.pc.destruct = genericDestruct;
1823 pcw->pci.pc.print = genericPrint;
1825 pcw->id = pCodeID; // this is the 'n' in %n
1826 pcw->operand = optional_operand;
1827 pcw->label = optional_label;
1829 pcw->mustBeBitSkipInst = 0;
1830 pcw->mustNotBeBitSkipInst = 0;
1831 pcw->invertBitSkipInst = 0;
1833 return ( (pCode *)pcw);
1837 /*-----------------------------------------------------------------*/
1838 /* newPcodeInlineP - create a new pCode from a char string */
1839 /*-----------------------------------------------------------------*/
1842 pCode *newpCodeInlineP(char *cP)
1847 pcc = Safe_calloc(1,sizeof(pCodeComment));
1849 pcc->pc.type = PC_INLINE;
1850 pcc->pc.prev = pcc->pc.next = NULL;
1851 pcc->pc.id = PCodeID();
1852 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1855 // pcc->pc.analyze = genericAnalyze;
1856 pcc->pc.destruct = genericDestruct;
1857 pcc->pc.print = genericPrint;
1860 pcc->comment = Safe_strdup(cP);
1862 pcc->comment = NULL;
1864 return ( (pCode *)pcc);
1868 /*-----------------------------------------------------------------*/
1869 /* newPcodeCharP - create a new pCode from a char string */
1870 /*-----------------------------------------------------------------*/
1872 pCode *newpCodeCharP(char *cP)
1877 pcc = Safe_calloc(1,sizeof(pCodeComment));
1879 pcc->pc.type = PC_COMMENT;
1880 pcc->pc.prev = pcc->pc.next = NULL;
1881 pcc->pc.id = PCodeID();
1882 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1885 // pcc->pc.analyze = genericAnalyze;
1886 pcc->pc.destruct = genericDestruct;
1887 pcc->pc.print = genericPrint;
1890 pcc->comment = Safe_strdup(cP);
1892 pcc->comment = NULL;
1894 return ( (pCode *)pcc);
1898 /*-----------------------------------------------------------------*/
1899 /* newpCodeFunction - */
1900 /*-----------------------------------------------------------------*/
1903 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1907 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1908 //_ALLOC(pcf,sizeof(pCodeFunction));
1910 pcf->pc.type = PC_FUNCTION;
1911 pcf->pc.prev = pcf->pc.next = NULL;
1912 pcf->pc.id = PCodeID();
1913 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1916 // pcf->pc.analyze = genericAnalyze;
1917 pcf->pc.destruct = genericDestruct;
1918 pcf->pc.print = pCodePrintFunction;
1923 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1924 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1925 strcpy(pcf->modname,mod);
1927 pcf->modname = NULL;
1930 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1931 pcf->fname = Safe_calloc(1,strlen(f)+1);
1932 strcpy(pcf->fname,f);
1936 pcf->isPublic = (unsigned)isPublic;
1938 return ( (pCode *)pcf);
1942 /*-----------------------------------------------------------------*/
1944 /*-----------------------------------------------------------------*/
1945 void destructpCodeFlow(pCode *pc)
1947 if(!pc || !isPCFL(pc))
1956 deleteSet(&PCFL(pc)->registers);
1957 deleteSet(&PCFL(pc)->from);
1958 deleteSet(&PCFL(pc)->to);
1963 pCode *newpCodeFlow(void )
1967 //_ALLOC(pcflow,sizeof(pCodeFlow));
1968 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1970 pcflow->pc.type = PC_FLOW;
1971 pcflow->pc.prev = pcflow->pc.next = NULL;
1972 pcflow->pc.pb = NULL;
1974 // pcflow->pc.analyze = genericAnalyze;
1975 pcflow->pc.destruct = destructpCodeFlow;
1976 pcflow->pc.print = genericPrint;
1978 pcflow->pc.seq = GpcFlowSeq++;
1980 pcflow->from = pcflow->to = NULL;
1982 pcflow->inCond = PCC_NONE;
1983 pcflow->outCond = PCC_NONE;
1985 pcflow->firstBank = 'U'; /* Undetermined */
1986 pcflow->lastBank = 'U'; /* Undetermined */
1988 pcflow->FromConflicts = 0;
1989 pcflow->ToConflicts = 0;
1993 pcflow->registers = newSet();
1995 return ( (pCode *)pcflow);
1999 /*-----------------------------------------------------------------*/
2000 /*-----------------------------------------------------------------*/
2001 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2003 pCodeFlowLink *pcflowLink;
2005 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2007 pcflowLink->pcflow = pcflow;
2008 pcflowLink->bank_conflict = 0;
2013 /*-----------------------------------------------------------------*/
2014 /* newpCodeCSource - create a new pCode Source Symbol */
2015 /*-----------------------------------------------------------------*/
2017 pCode *newpCodeCSource(int ln, char *f, const char *l)
2022 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2024 pccs->pc.type = PC_CSOURCE;
2025 pccs->pc.prev = pccs->pc.next = NULL;
2026 pccs->pc.id = PCodeID();
2029 pccs->pc.destruct = genericDestruct;
2030 pccs->pc.print = genericPrint;
2032 pccs->line_number = ln;
2034 pccs->line = Safe_strdup(l);
2039 pccs->file_name = Safe_strdup(f);
2041 pccs->file_name = NULL;
2043 return ( (pCode *)pccs);
2047 /*******************************************************************/
2048 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2049 /* added by VR 6-Jun-2003 */
2050 /*******************************************************************/
2052 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2059 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2060 pcad->pci.pc.type = PC_ASMDIR;
2061 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2062 pcad->pci.pc.pb = NULL;
2063 pcad->pci.pc.destruct = genericDestruct;
2064 pcad->pci.pc.print = genericPrint;
2066 if(asdir && *asdir) {
2068 while(isspace(*asdir))asdir++; // strip any white space from the beginning
2070 pcad->directive = Safe_strdup( asdir );
2073 va_start(ap, argfmt);
2075 memset(buffer, 0, sizeof(buffer));
2076 if(argfmt && *argfmt)
2077 vsprintf(buffer, argfmt, ap);
2081 while(isspace(*lbp))lbp++;
2084 pcad->arg = Safe_strdup( lbp );
2086 return ((pCode *)pcad);
2089 /*-----------------------------------------------------------------*/
2090 /* pCodeLabelDestruct - free memory used by a label. */
2091 /*-----------------------------------------------------------------*/
2092 static void pCodeLabelDestruct(pCode *pc)
2098 if((pc->type == PC_LABEL) && PCL(pc)->label)
2099 free(PCL(pc)->label);
2105 pCode *newpCodeLabel(char *name, int key)
2111 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2113 pcl->pc.type = PC_LABEL;
2114 pcl->pc.prev = pcl->pc.next = NULL;
2115 pcl->pc.id = PCodeID();
2116 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2119 // pcl->pc.analyze = genericAnalyze;
2120 pcl->pc.destruct = pCodeLabelDestruct;
2121 pcl->pc.print = pCodePrintLabel;
2127 sprintf(s,"_%05d_DS_",key);
2132 pcl->label = Safe_strdup(s);
2134 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2135 return ( (pCode *)pcl);
2140 /*-----------------------------------------------------------------*/
2141 /* newpBlock - create and return a pointer to a new pBlock */
2142 /*-----------------------------------------------------------------*/
2143 pBlock *newpBlock(void)
2148 PpB = Safe_calloc(1,sizeof(pBlock) );
2149 PpB->next = PpB->prev = NULL;
2151 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2152 PpB->tregisters = NULL;
2154 PpB->FlowTree = NULL;
2160 /*-----------------------------------------------------------------*/
2161 /* newpCodeChain - create a new chain of pCodes */
2162 /*-----------------------------------------------------------------*
2164 * This function will create a new pBlock and the pointer to the
2165 * pCode that is passed in will be the first pCode in the block.
2166 *-----------------------------------------------------------------*/
2169 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2172 pBlock *pB = newpBlock();
2174 pB->pcHead = pB->pcTail = pc;
2181 /*-----------------------------------------------------------------*/
2182 /* newpCodeOpLabel - Create a new label given the key */
2183 /* Note, a negative key means that the label is part of wild card */
2184 /* (and hence a wild card label) used in the pCodePeep */
2185 /* optimizations). */
2186 /*-----------------------------------------------------------------*/
2188 pCodeOp *newpCodeOpLabel(char *name, int key)
2191 static int label_key=-1;
2195 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2196 pcop->type = PO_LABEL;
2201 sprintf(s=buffer,"_%05d_DS_",key);
2203 s = name, key = label_key--;
2205 PCOLAB(pcop)->offset = 0;
2207 pcop->name = Safe_strdup(s);
2209 ((pCodeOpLabel *)pcop)->key = key;
2211 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2215 /*-----------------------------------------------------------------*/
2216 /*-----------------------------------------------------------------*/
2217 pCodeOp *newpCodeOpLit(int lit)
2223 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2224 pcop->type = PO_LITERAL;
2228 sprintf(s,"0x%02x",lit);
2230 pcop->name = Safe_strdup(s);
2233 ((pCodeOpLit *)pcop)->lit = lit;
2238 /*-----------------------------------------------------------------*/
2239 /*-----------------------------------------------------------------*/
2240 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2244 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2245 pcop->type = PO_IMMEDIATE;
2248 pcop->name = Safe_strdup(name);
2251 r = dirregWithName(name);
2255 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2256 PCOI(pcop)->rIdx = r->rIdx;
2258 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2259 PCOI(pcop)->rIdx = -1;
2261 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2266 PCOI(pcop)->index = index;
2267 PCOI(pcop)->offset = offset;
2268 PCOI(pcop)->_const = code_space;
2269 PCOI(pcop)->_function = is_func;
2274 /*-----------------------------------------------------------------*/
2275 /*-----------------------------------------------------------------*/
2276 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2282 if(!pcwb || !subtype) {
2283 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2287 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2288 pcop->type = PO_WILD;
2289 sprintf(s,"%%%d",id);
2290 pcop->name = Safe_strdup(s);
2292 PCOW(pcop)->id = id;
2293 PCOW(pcop)->pcwb = pcwb;
2294 PCOW(pcop)->subtype = subtype;
2295 PCOW(pcop)->matched = NULL;
2299 /*-----------------------------------------------------------------*/
2300 /* Find a symbol with matching name */
2301 /*-----------------------------------------------------------------*/
2302 static symbol *symFindWithName(memmap * map, const char *name)
2306 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2307 if (sym->rname && (strcmp(sym->rname,name)==0))
2313 /*-----------------------------------------------------------------*/
2314 /*-----------------------------------------------------------------*/
2315 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2320 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2321 pcop->type = PO_GPR_BIT;
2323 PCORB(pcop)->bit = ibit;
2324 PCORB(pcop)->inBitSpace = inBitSpace;
2326 if (name) r = regFindWithName(name);
2328 // Register has not been allocated - check for symbol information
2330 sym = symFindWithName(bit, name);
2331 if (!sym) sym = symFindWithName(sfrbit, name);
2332 if (!sym) sym = symFindWithName(sfr, name);
2334 r = allocNewDirReg(sym->etype,name);
2340 PCOR(pcop)->rIdx = r->rIdx;
2342 pcop->name = Safe_strdup(name);
2343 PCOR(pcop)->r = NULL;
2344 PCOR(pcop)->rIdx = 0;
2349 /*-----------------------------------------------------------------*
2350 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2352 * If rIdx >=0 then a specific register from the set of registers
2353 * will be selected. If rIdx <0, then a new register will be searched
2355 *-----------------------------------------------------------------*/
2357 pCodeOp *newpCodeOpReg(int rIdx)
2361 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2366 PCOR(pcop)->rIdx = rIdx;
2367 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2369 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2372 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2376 pcop->type = PCOR(pcop)->r->pc_type;
2381 pCodeOp *newpCodeOpRegFromStr(char *name)
2385 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2386 PCOR(pcop)->r = allocRegByName(name, 1);
2387 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2388 pcop->type = PCOR(pcop)->r->pc_type;
2389 pcop->name = PCOR(pcop)->r->name;
2394 pCodeOp *newpCodeOpStr(char *name)
2398 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2399 pcop->type = PO_STR;
2400 pcop->name = Safe_strdup(name);
2402 PCOS(pcop)->isPublic = 0;
2408 /*-----------------------------------------------------------------*/
2409 /*-----------------------------------------------------------------*/
2411 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2418 pcop = newpCodeOpBit(name, -1,0);
2422 pcop = newpCodeOpLit(-1);
2426 pcop = newpCodeOpLabel(NULL,-1);
2430 pcop = newpCodeOpReg(-1);
2433 case PO_GPR_POINTER:
2434 case PO_GPR_REGISTER:
2436 pcop = newpCodeOpRegFromStr(name);
2438 pcop = newpCodeOpReg(-1);
2442 pcop = newpCodeOpStr(name);
2446 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2449 pcop->name = Safe_strdup(name);
2457 /*-----------------------------------------------------------------*/
2458 /*-----------------------------------------------------------------*/
2459 void pCodeConstString(char *name, char *value)
2464 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2469 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2473 sprintf(buffer,"; %s = %s",name,value);
2474 for (i=strlen(buffer); i--; ) {
2475 unsigned char c = buffer[i];
2476 if (c=='\r' || c=='\n') {
2477 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2479 if (c=='\r') buffer[i+1] = 'r';
2480 else if (c=='\n') buffer[i+1] = 'n';
2484 addpCode2pBlock(pb,newpCodeCharP(buffer));
2485 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2488 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2494 /*-----------------------------------------------------------------*/
2495 /*-----------------------------------------------------------------*/
2496 void pCodeReadCodeTable(void)
2500 fprintf(stderr, " %s\n",__FUNCTION__);
2502 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2506 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2507 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2508 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2509 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2511 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2512 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2513 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2514 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2519 /*-----------------------------------------------------------------*/
2520 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2521 /*-----------------------------------------------------------------*/
2522 void addpCode2pBlock(pBlock *pb, pCode *pc)
2529 /* If this is the first pcode to be added to a block that
2530 * was initialized with a NULL pcode, then go ahead and
2531 * make this pcode the head and tail */
2532 pb->pcHead = pb->pcTail = pc;
2535 pb->pcTail->next = pc;
2537 pc->prev = pb->pcTail;
2544 /*-----------------------------------------------------------------*/
2545 /* addpBlock - place a pBlock into the pFile */
2546 /*-----------------------------------------------------------------*/
2547 void addpBlock(pBlock *pb)
2549 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2552 /* First time called, we'll pass through here. */
2553 //_ALLOC(the_pFile,sizeof(pFile));
2554 the_pFile = Safe_calloc(1,sizeof(pFile));
2555 the_pFile->pbHead = the_pFile->pbTail = pb;
2556 the_pFile->functions = NULL;
2560 the_pFile->pbTail->next = pb;
2561 pb->prev = the_pFile->pbTail;
2563 the_pFile->pbTail = pb;
2566 /*-----------------------------------------------------------------*/
2567 /* removepBlock - remove a pBlock from the pFile */
2568 /*-----------------------------------------------------------------*/
2569 void removepBlock(pBlock *pb)
2577 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2579 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2582 if(pbs == the_pFile->pbHead)
2583 the_pFile->pbHead = pbs->next;
2585 if (pbs == the_pFile->pbTail)
2586 the_pFile->pbTail = pbs->prev;
2589 pbs->next->prev = pbs->prev;
2592 pbs->prev->next = pbs->next;
2599 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2603 /*-----------------------------------------------------------------*/
2604 /* printpCode - write the contents of a pCode to a file */
2605 /*-----------------------------------------------------------------*/
2606 void printpCode(FILE *of, pCode *pc)
2617 fprintf(of,"warning - unable to print pCode\n");
2620 /*-----------------------------------------------------------------*/
2621 /* printpBlock - write the contents of a pBlock to a file */
2622 /*-----------------------------------------------------------------*/
2623 void printpBlock(FILE *of, pBlock *pb)
2633 for(pc = pb->pcHead; pc; pc = pc->next) {
2638 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2648 /*-----------------------------------------------------------------*/
2650 /* pCode processing */
2654 /*-----------------------------------------------------------------*/
2656 void unlinkpCode(pCode *pc)
2662 fprintf(stderr,"Unlinking: ");
2663 printpCode(stderr, pc);
2666 pc->prev->next = pc->next;
2668 pc->next->prev = pc->prev;
2670 pc->prev = pc->next = NULL;
2674 /*-----------------------------------------------------------------*/
2675 /*-----------------------------------------------------------------*/
2677 static void genericDestruct(pCode *pc)
2683 /* For instructions, tell the register (if there's one used)
2684 * that it's no longer needed */
2685 regs *reg = getRegFromInstruction(pc);
2687 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2690 /* Instead of deleting the memory used by this pCode, mark
2691 * the object as bad so that if there's a pointer to this pCode
2692 * dangling around somewhere then (hopefully) when the type is
2693 * checked we'll catch it.
2698 addpCode2pBlock(pb_dead_pcodes, pc);
2705 /*-----------------------------------------------------------------*/
2706 /* Copies the pCodeInstruction flow pointer from source pCode */
2707 /*-----------------------------------------------------------------*/
2708 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2710 pCodeFlow *pcflow = 0;
2711 for (p=pcs; p; p=p->prev) {
2713 pcflow = PCI(p)->pcflow;
2717 pcflow = (pCodeFlow*)p;
2721 PCI(pcd)->pcflow = pcflow;
2724 /*-----------------------------------------------------------------*/
2725 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2726 /* into the pCode chain containing pc1 */
2727 /*-----------------------------------------------------------------*/
2728 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2734 pc2->next = pc1->next;
2736 pc1->next->prev = pc2;
2742 /* If this is an instrution type propogate the flow */
2744 CopyFlow(PCI(pc2),pc1);
2747 /*------------------------------------------------------------------*/
2748 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2749 /* into the pCode chain containing pc1 */
2750 /*------------------------------------------------------------------*/
2751 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2757 pc2->prev = pc1->prev;
2759 pc1->prev->next = pc2;
2765 /* If this is an instrution type propogate the flow */
2767 CopyFlow(PCI(pc2),pc1);
2770 /*-----------------------------------------------------------------*/
2771 /* pCodeOpCopy - copy a pcode operator */
2772 /*-----------------------------------------------------------------*/
2773 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2775 pCodeOp *pcopnew=NULL;
2780 switch(pcop->type) {
2783 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2784 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2785 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2786 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2791 /* Here we expand the wild card into the appropriate type: */
2792 /* By recursively calling pCodeOpCopy */
2793 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2794 if(PCOW(pcop)->matched)
2795 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2798 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2799 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2800 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2807 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2808 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2809 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2813 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2814 PCOI(pcopnew)->index = PCOI(pcop)->index;
2815 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2816 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2817 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2821 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2822 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2823 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2828 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2829 PCOR(pcopnew)->r = PCOR(pcop)->r;
2830 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2831 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2835 case PO_GPR_POINTER:
2836 case PO_GPR_REGISTER:
2840 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2841 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2842 PCOR(pcopnew)->r = PCOR(pcop)->r;
2843 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2844 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2845 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2849 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2850 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2851 PCOR(pcopnew)->r = PCOR(pcop)->r;
2852 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2853 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2856 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2857 case PO_SFR_REGISTER:
2865 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2866 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2870 pcopnew->type = pcop->type;
2872 pcopnew->name = Safe_strdup(pcop->name);
2874 pcopnew->name = NULL;
2879 /*-----------------------------------------------------------------*/
2880 /* popCopyReg - copy a pcode operator */
2881 /*-----------------------------------------------------------------*/
2882 pCodeOp *popCopyReg(pCodeOpReg *pc)
2886 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2887 pcor->pcop.type = pc->pcop.type;
2889 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2890 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2892 pcor->pcop.name = NULL;
2894 if (pcor->pcop.type == PO_IMMEDIATE){
2895 PCOL(pcor)->lit = PCOL(pc)->lit;
2898 pcor->rIdx = pc->rIdx;
2902 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2907 /*-----------------------------------------------------------------*/
2908 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2909 /*-----------------------------------------------------------------*/
2910 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2912 pCodeInstruction *new_pci;
2915 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2917 new_pci = PCI(newpCode(pci->op,pci->pcop));
2919 new_pci->pc.pb = pci->pc.pb;
2920 new_pci->from = pci->from;
2921 new_pci->to = pci->to;
2922 new_pci->label = pci->label;
2923 new_pci->pcflow = pci->pcflow;
2925 return PCODE(new_pci);
2928 /*-----------------------------------------------------------------*/
2929 /*-----------------------------------------------------------------*/
2930 void pCodeDeleteChain(pCode *f,pCode *t)
2935 DFPRINTF((stderr,"delete pCode:\n"));
2937 //f->print(stderr,f);
2938 //f->delete(f); this dumps core...
2943 /*-----------------------------------------------------------------*/
2944 /*-----------------------------------------------------------------*/
2945 void pBlockRegs(FILE *of, pBlock *pb)
2950 r = setFirstItem(pb->tregisters);
2952 r = setNextItem(pb->tregisters);
2957 /*-----------------------------------------------------------------*/
2958 /*-----------------------------------------------------------------*/
2959 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2964 int use_buffer = 1; // copy the string to the passed buffer pointer
2969 use_buffer = 0; // Don't bother copying the string to the buffer.
2973 switch(pcop->type) {
2977 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2980 //return PCOR(pcop)->r->name;
2984 if (PCOR(pcop)->r->type == REG_STK)
2985 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2987 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2990 SAFE_snprintf(&buffer,&size,"%s",r->name);
2999 if(PCOI(pcop)->_const) {
3001 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3002 switch(PCOI(pcop)->offset) {
3004 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3007 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3010 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3011 assert ( !"offset too large" );
3012 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3015 8 * PCOI(pcop)->offset );
3018 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3020 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) {
3021 SAFE_snprintf(&s,&size,"(%s + %d)",
3025 switch(PCOI(pcop)->offset) {
3027 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3030 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3033 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3034 assert ( !"offset too large" );
3035 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3045 //size = sizeof(buffer);
3046 if( PCOR(pcop)->instance) {
3047 SAFE_snprintf(&s,&size,"(%s + %d)",
3049 PCOR(pcop)->instance );
3050 //fprintf(stderr,"PO_DIR %s\n",buffer);
3052 SAFE_snprintf(&s,&size,"%s",pcop->name);
3058 if(PCOLAB(pcop)->offset == 1)
3059 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3061 SAFE_snprintf(&s,&size,"%s",pcop->name);
3068 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3071 return PCOR(pcop)->r->name;
3074 /* fall through to the default case */
3078 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3086 printf("PIC port internal warning: (%s:%d) %s not found\n",
3091 return "NO operand";
3095 /*-----------------------------------------------------------------*/
3096 /*-----------------------------------------------------------------*/
3097 static char *get_op_from_instruction( pCodeInstruction *pcc)
3101 return get_op(pcc->pcop,NULL,0);
3103 return ("ERROR Null: get_op_from_instruction");
3107 /*-----------------------------------------------------------------*/
3108 /*-----------------------------------------------------------------*/
3109 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3111 fprintf(of,"pcodeopprint- not implemented\n");
3114 /*-----------------------------------------------------------------*/
3115 /* pCode2str - convert a pCode instruction to string */
3116 /*-----------------------------------------------------------------*/
3117 char *pCode2str(char *str, size_t size, pCode *pc)
3125 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3127 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3129 if(PCI(pc)->isBitInst) {
3130 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3131 char *name = PCI(pc)->pcop->name;
3133 name = PCOR(PCI(pc)->pcop)->r->name;
3134 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3135 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3137 SAFE_snprintf(&s,&size,"%s,%d", name,
3138 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3139 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3140 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3142 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3143 //PCI(pc)->pcop->t.bit );
3145 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3146 if( PCI(pc)->num_ops == 2)
3147 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3149 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3151 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3152 if( PCI(pc)->num_ops == 2)
3153 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3160 /* assuming that comment ends with a \n */
3161 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3165 /* assuming that inline code ends with a \n */
3166 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3170 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3173 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3176 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3179 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3182 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3185 if(PCAD(pc)->directive) {
3186 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3187 } else if(PCAD(pc)->arg) {
3188 /* special case to handle inline labels without a tab */
3189 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3194 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3200 /*-----------------------------------------------------------------*/
3201 /* genericPrint - the contents of a pCode to a file */
3202 /*-----------------------------------------------------------------*/
3203 static void genericPrint(FILE *of, pCode *pc)
3210 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3214 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3218 // If the opcode has a label, print that first
3221 pCodeInstruction *pci = PCI(pc);
3222 pBranch *pbl = pci->label;
3223 while(pbl && pbl->pc) {
3224 if(pbl->pc->type == PC_LABEL)
3225 pCodePrintLabel(of, pbl->pc);
3230 genericPrint(of,PCODE(pci->cline));
3233 pCode2str(str, 256, pc);
3235 fprintf(of,"%s",str);
3239 pCodeOpReg *pcor = PCOR(pci->pcop);
3240 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3242 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3243 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3244 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3249 pBranch *dpb = pc->to; // debug
3251 switch ( dpb->pc->type) {
3253 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3256 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3259 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3262 fprintf(of, "\t;flow");
3276 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3277 if(PCW(pc)->pci.label)
3278 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3280 if(PCW(pc)->operand) {
3281 fprintf(of,";\toperand ");
3282 pCodeOpPrint(of,PCW(pc)->operand );
3288 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3289 if(PCFL(pc)->ancestor)
3290 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3296 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3301 pBranch *pbl = PCAD(pc)->pci.label;
3302 while(pbl && pbl->pc) {
3303 if(pbl->pc->type == PC_LABEL)
3304 pCodePrintLabel(of, pbl->pc);
3308 if(PCAD(pc)->directive) {
3309 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3312 /* special case to handle inline labels without tab */
3313 fprintf(of, "%s\n", PCAD(pc)->arg);
3319 fprintf(of,"unknown pCode type %d\n",pc->type);
3323 /*-----------------------------------------------------------------*/
3324 /* pCodePrintFunction - prints function begin/end */
3325 /*-----------------------------------------------------------------*/
3327 static void pCodePrintFunction(FILE *of, pCode *pc)
3333 if( ((pCodeFunction *)pc)->modname)
3334 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3336 if(PCF(pc)->fname) {
3337 pBranch *exits = PCF(pc)->to;
3339 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3342 exits = exits->next;
3345 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3348 if((PCF(pc)->from &&
3349 PCF(pc)->from->pc->type == PC_FUNCTION &&
3350 PCF(PCF(pc)->from->pc)->fname) )
3351 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3353 fprintf(of,"; exit point [can't find entry point]\n");
3356 /*-----------------------------------------------------------------*/
3357 /* pCodePrintLabel - prints label */
3358 /*-----------------------------------------------------------------*/
3360 static void pCodePrintLabel(FILE *of, pCode *pc)
3367 fprintf(of,"%s\n",PCL(pc)->label);
3368 else if (PCL(pc)->key >=0)
3369 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3371 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3375 /*-----------------------------------------------------------------*/
3376 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3377 /* remove it if it is found. */
3378 /*-----------------------------------------------------------------*/
3379 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3385 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3386 b = PCI(pcl)->label;
3388 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3392 //fprintf (stderr, "%s \n",__FUNCTION__);
3393 //pcl->print(stderr,pcl);
3394 //pc->print(stderr,pc);
3397 //fprintf (stderr, "found label\n");
3401 bprev->next = b->next; /* Not first pCode in chain */
3405 PCI(pcl)->label = b->next; /* First pCode in chain */
3408 return; /* A label can't occur more than once */
3415 /*-----------------------------------------------------------------*/
3416 /*-----------------------------------------------------------------*/
3417 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3436 /*-----------------------------------------------------------------*/
3437 /* pBranchLink - given two pcodes, this function will link them */
3438 /* together through their pBranches */
3439 /*-----------------------------------------------------------------*/
3440 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3444 // Declare a new branch object for the 'from' pCode.
3446 //_ALLOC(b,sizeof(pBranch));
3447 b = Safe_calloc(1,sizeof(pBranch));
3448 b->pc = PCODE(t); // The link to the 'to' pCode.
3451 f->to = pBranchAppend(f->to,b);
3453 // Now do the same for the 'to' pCode.
3455 //_ALLOC(b,sizeof(pBranch));
3456 b = Safe_calloc(1,sizeof(pBranch));
3460 t->from = pBranchAppend(t->from,b);
3465 /*-----------------------------------------------------------------*/
3466 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3468 /*-----------------------------------------------------------------*/
3469 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3482 /*-----------------------------------------------------------------*/
3483 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3484 /*-----------------------------------------------------------------*/
3485 static void pCodeUnlink(pCode *pc)
3490 if(!pc->prev || !pc->next) {
3491 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3495 /* first remove the pCode from the chain */
3496 pc->prev->next = pc->next;
3497 pc->next->prev = pc->prev;
3499 /* Now for the hard part... */
3501 /* Remove the branches */
3505 pc1 = pb1->pc; /* Get the pCode that branches to the
3506 * one we're unlinking */
3508 /* search for the link back to this pCode (the one we're
3510 if(pb2 = pBranchFind(pc1->to,pc)) {
3511 pb2->pc = pc->to->pc; // make the replacement
3513 /* if the pCode we're unlinking contains multiple 'to'
3514 * branches (e.g. this a skip instruction) then we need
3515 * to copy these extra branches to the chain. */
3517 pBranchAppend(pb2, pc->to->next);
3526 /*-----------------------------------------------------------------*/
3527 /*-----------------------------------------------------------------*/
3529 static void genericAnalyze(pCode *pc)
3539 // Go through the pCodes that are in pCode chain and link
3540 // them together through the pBranches. Note, the pCodes
3541 // are linked together as a contiguous stream like the
3542 // assembly source code lines. The linking here mimics this
3543 // except that comments are not linked in.
3545 pCode *npc = pc->next;
3547 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3548 pBranchLink(pc,npc);
3553 /* reached the end of the pcode chain without finding
3554 * an instruction we could link to. */
3558 fprintf(stderr,"analyze PC_FLOW\n");
3562 fprintf(stderr,";A bad pCode is being used\n");
3568 /*-----------------------------------------------------------------*/
3569 /*-----------------------------------------------------------------*/
3570 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3574 if(pc->type == PC_LABEL) {
3575 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3578 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3579 pbr = PCI(pc)->label;
3581 if(pbr->pc->type == PC_LABEL) {
3582 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3592 /*-----------------------------------------------------------------*/
3593 /*-----------------------------------------------------------------*/
3594 int checkLabel(pCode *pc)
3598 if(pc && isPCI(pc)) {
3599 pbr = PCI(pc)->label;
3601 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3611 /*-----------------------------------------------------------------*/
3612 /* findLabelinpBlock - Search the pCode for a particular label */
3613 /*-----------------------------------------------------------------*/
3614 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3621 for(pc = pb->pcHead; pc; pc = pc->next)
3622 if(compareLabel(pc,pcop_label))
3628 /*-----------------------------------------------------------------*/
3629 /* findLabel - Search the pCode for a particular label */
3630 /*-----------------------------------------------------------------*/
3631 pCode * findLabel(pCodeOpLabel *pcop_label)
3639 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3640 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3644 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3648 /*-----------------------------------------------------------------*/
3649 /* findNextpCode - given a pCode, find the next of type 'pct' */
3650 /* in the linked list */
3651 /*-----------------------------------------------------------------*/
3652 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3665 /*-----------------------------------------------------------------*/
3666 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3667 /* in the linked list */
3668 /*-----------------------------------------------------------------*/
3669 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3673 if(pc->type == pct) {
3675 static unsigned int stop;
3677 stop++; // Place break point here
3688 /*-----------------------------------------------------------------*/
3689 /* findNextInstruction - given a pCode, find the next instruction */
3690 /* in the linked list */
3691 /*-----------------------------------------------------------------*/
3692 pCode * findNextInstruction(pCode *pci)
3697 if((pc->type == PC_OPCODE)
3698 || (pc->type == PC_WILD)
3699 || (pc->type == PC_ASMDIR))
3703 fprintf(stderr,"findNextInstruction: ");
3704 printpCode(stderr, pc);
3709 //fprintf(stderr,"Couldn't find instruction\n");
3713 /*-----------------------------------------------------------------*/
3714 /* findNextInstruction - given a pCode, find the next instruction */
3715 /* in the linked list */
3716 /*-----------------------------------------------------------------*/
3717 pCode * findPrevInstruction(pCode *pci)
3723 if((pc->type == PC_OPCODE)
3724 || (pc->type == PC_WILD)
3725 || (pc->type == PC_ASMDIR))
3730 fprintf(stderr,"pic16_findPrevInstruction: ");
3731 printpCode(stderr, pc);
3736 //fprintf(stderr,"Couldn't find instruction\n");
3740 /*-----------------------------------------------------------------*/
3741 /* findFunctionEnd - given a pCode find the end of the function */
3742 /* that contains it */
3743 /*-----------------------------------------------------------------*/
3744 pCode * findFunctionEnd(pCode *pc)
3747 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3753 fprintf(stderr,"Couldn't find function end\n");
3758 /*-----------------------------------------------------------------*/
3759 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3760 /* instruction with which it is associated. */
3761 /*-----------------------------------------------------------------*/
3762 static void AnalyzeLabel(pCode *pc)
3771 static void AnalyzeGOTO(pCode *pc)
3774 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3778 static void AnalyzeSKIP(pCode *pc)
3781 pBranchLink(pc,findNextInstruction(pc->next));
3782 pBranchLink(pc,findNextInstruction(pc->next->next));
3786 static void AnalyzeRETURN(pCode *pc)
3789 // branch_link(pc,findFunctionEnd(pc->next));
3795 /*-----------------------------------------------------------------*/
3796 /*-----------------------------------------------------------------*/
3797 regs * getRegFromInstruction(pCode *pc)
3803 PCI(pc)->num_ops == 0 )
3806 switch(PCI(pc)->pcop->type) {
3809 return PCOR(PCI(pc)->pcop)->r;
3813 return PCOR(PCI(pc)->pcop)->r;
3816 r = PCOI(PCI(pc)->pcop)->r;
3819 return dirregWithName(PCI(pc)->pcop->name);
3822 r = PCOR(PCI(pc)->pcop)->r;
3825 return dirregWithName(PCI(pc)->pcop->name);
3827 case PO_GPR_REGISTER:
3829 r = PCOR(PCI(pc)->pcop)->r;
3832 return dirregWithName(PCI(pc)->pcop->name);
3844 /*-----------------------------------------------------------------*/
3845 /*-----------------------------------------------------------------*/
3847 void AnalyzepBlock(pBlock *pb)
3854 /* Find all of the registers used in this pBlock
3855 * by looking at each instruction and examining it's
3858 for(pc = pb->pcHead; pc; pc = pc->next) {
3860 /* Is this an instruction with operands? */
3861 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3863 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3864 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3866 /* Loop through all of the registers declared so far in
3867 this block and see if we find this one there */
3869 regs *r = setFirstItem(pb->tregisters);
3872 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3873 PCOR(PCI(pc)->pcop)->r = r;
3876 r = setNextItem(pb->tregisters);
3880 /* register wasn't found */
3881 //r = Safe_calloc(1, sizeof(regs));
3882 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3883 //addSet(&pb->tregisters, r);
3884 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3885 //PCOR(PCI(pc)->pcop)->r = r;
3886 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3888 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3891 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3892 if(PCOR(PCI(pc)->pcop)->r) {
3893 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3894 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3896 if(PCI(pc)->pcop->name)
3897 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3899 fprintf(stderr,"ERROR: NULL register\n");
3908 /*-----------------------------------------------------------------*/
3910 /*-----------------------------------------------------------------*/
3911 void InsertpFlow(pCode *pc, pCode **pflow)
3914 PCFL(*pflow)->end = pc;
3916 if(!pc || !pc->next)
3919 *pflow = newpCodeFlow();
3920 pCodeInsertAfter(pc, *pflow);
3923 /*-----------------------------------------------------------------*/
3924 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3925 /* the flow blocks. */
3927 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3928 * point the instruction flow changes.
3930 /*-----------------------------------------------------------------*/
3931 void BuildFlow(pBlock *pb)
3934 pCode *last_pci=NULL;
3941 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3942 /* Insert a pCodeFlow object at the beginning of a pBlock */
3944 InsertpFlow(pb->pcHead, &pflow);
3946 //pflow = newpCodeFlow(); /* Create a new Flow object */
3947 //pflow->next = pb->pcHead; /* Make the current head the next object */
3948 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3949 //pb->pcHead = pflow; /* Make the Flow object the head */
3952 for( pc = findNextInstruction(pb->pcHead);
3954 pc=findNextInstruction(pc)) {
3957 PCI(pc)->pcflow = PCFL(pflow);
3959 //fprintf(stderr," build: ");
3960 //pflow->print(stderr,pflow);
3962 if( PCI(pc)->isSkip) {
3964 /* The two instructions immediately following this one
3965 * mark the beginning of a new flow segment */
3967 while(pc && PCI(pc)->isSkip) {
3969 PCI(pc)->pcflow = PCFL(pflow);
3973 InsertpFlow(pc, &pflow);
3974 pc=findNextInstruction(pc->next);
3982 PCI(pc)->pcflow = PCFL(pflow);
3984 InsertpFlow(pc, &pflow);
3986 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
3988 InsertpFlow(pc, &pflow);
3991 } else if (checkLabel(pc)) {
3993 /* This instruction marks the beginning of a
3994 * new flow segment */
3999 /* If the previous pCode is not a flow object, then
4000 * insert a new flow object. (This check prevents
4001 * two consecutive flow objects from being insert in
4002 * the case where a skip instruction preceeds an
4003 * instruction containing a label.) */
4005 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4006 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
4008 PCI(pc)->pcflow = PCFL(pflow);
4015 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4017 PCFL(pflow)->end = pb->pcTail;
4020 /*-------------------------------------------------------------------*/
4021 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4022 /* the flow blocks. */
4024 * unBuildFlow removes pCodeFlow objects from a pCode chain
4026 /*-----------------------------------------------------------------*/
4027 void unBuildFlow(pBlock *pb)
4042 if(PCI(pc)->pcflow) {
4043 //free(PCI(pc)->pcflow);
4044 PCI(pc)->pcflow = NULL;
4047 } else if(isPCFL(pc) )
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 void dumpCond(int cond)
4061 static char *pcc_str[] = {
4075 int ncond = sizeof(pcc_str) / sizeof(char *);
4078 fprintf(stderr, "0x%04X\n",cond);
4080 for(i=0,j=1; i<ncond; i++, j<<=1)
4082 fprintf(stderr, " %s\n",pcc_str[i]);
4086 /*-----------------------------------------------------------------*/
4087 /*-----------------------------------------------------------------*/
4088 void FlowStats(pCodeFlow *pcflow)
4096 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4098 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4101 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4106 fprintf(stderr, " FlowStats inCond: ");
4107 dumpCond(pcflow->inCond);
4108 fprintf(stderr, " FlowStats outCond: ");
4109 dumpCond(pcflow->outCond);
4113 /*-----------------------------------------------------------------*
4114 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4115 * if it affects the banking bits.
4117 * return: -1 == Banking bits are unaffected by this pCode.
4119 * return: > 0 == Banking bits are affected.
4121 * If the banking bits are affected, then the returned value describes
4122 * which bits are affected and how they're affected. The lower half
4123 * of the integer maps to the bits that are affected, the upper half
4124 * to whether they're set or cleared.
4126 *-----------------------------------------------------------------*/
4128 #define SET_BANK_BIT (1 << 16)
4129 #define CLR_BANK_BIT 0
4131 static int isBankInstruction(pCode *pc)
4139 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4141 // Check to see if the register banks are changing
4142 if(PCI(pc)->isModReg) {
4144 pCodeOp *pcop = PCI(pc)->pcop;
4145 switch(PCI(pc)->op) {
4148 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4149 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4150 return SET_BANK_BIT | PIC_RP0_BIT;
4153 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4154 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4155 return CLR_BANK_BIT | PIC_RP0_BIT;
4160 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4161 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4162 return CLR_BANK_BIT | PIC_RP1_BIT;
4164 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4165 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4166 return CLR_BANK_BIT | PIC_RP1_BIT;
4170 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4171 //genericPrint(stderr, pc);
4182 /*-----------------------------------------------------------------*/
4183 /*-----------------------------------------------------------------*/
4185 static void FillFlow(pCodeFlow *pcflow)
4193 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4195 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4198 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4205 isBankInstruction(pc);
4207 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4210 fprintf(stderr, " FillFlow - Bad end of flow\n");
4212 fprintf(stderr, " FillFlow - Ending flow with\n ");
4213 pc->print(stderr,pc);
4216 fprintf(stderr, " FillFlow inCond: ");
4217 dumpCond(pcflow->inCond);
4218 fprintf(stderr, " FillFlow outCond: ");
4219 dumpCond(pcflow->outCond);
4224 /*-----------------------------------------------------------------*/
4225 /*-----------------------------------------------------------------*/
4226 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4228 pCodeFlowLink *fromLink, *toLink;
4230 if(!from || !to || !to->pcflow || !from->pcflow)
4233 fromLink = newpCodeFlowLink(from->pcflow);
4234 toLink = newpCodeFlowLink(to->pcflow);
4236 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4237 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4241 /*-----------------------------------------------------------------*
4242 * void LinkFlow(pBlock *pb)
4244 * In BuildFlow, the PIC code has been partitioned into contiguous
4245 * non-branching segments. In LinkFlow, we determine the execution
4246 * order of these segments. For example, if one of the segments ends
4247 * with a skip, then we know that there are two possible flow segments
4248 * to which control may be passed.
4249 *-----------------------------------------------------------------*/
4250 void LinkFlow(pBlock *pb)
4256 //fprintf(stderr,"linkflow \n");
4258 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4260 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4263 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4265 //fprintf(stderr," link: ");
4266 //pcflow->print(stderr,pcflow);
4268 //FillFlow(PCFL(pcflow));
4270 pc = PCFL(pcflow)->end;
4272 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4273 if(isPCI_SKIP(pc)) {
4274 //fprintf(stderr, "ends with skip\n");
4275 //pc->print(stderr,pc);
4276 pct=findNextInstruction(pc->next);
4277 LinkFlow_pCode(PCI(pc),PCI(pct));
4278 pct=findNextInstruction(pct->next);
4279 LinkFlow_pCode(PCI(pc),PCI(pct));
4283 if(isPCI_BRANCH(pc)) {
4284 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4286 //fprintf(stderr, "ends with branch\n ");
4287 //pc->print(stderr,pc);
4289 if(!(pcol && isPCOLAB(pcol))) {
4290 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4291 pc->print(stderr,pc);
4292 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4297 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4298 LinkFlow_pCode(PCI(pc),PCI(pct));
4300 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4301 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4302 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4308 //fprintf(stderr, "ends with non-branching instruction:\n");
4309 //pc->print(stderr,pc);
4311 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4317 //fprintf(stderr, "ends with unknown\n");
4318 //pc->print(stderr,pc);
4322 //fprintf(stderr, "ends with nothing: ERROR\n");
4326 /*-----------------------------------------------------------------*/
4327 /*-----------------------------------------------------------------*/
4329 /*-----------------------------------------------------------------*/
4330 /*-----------------------------------------------------------------*/
4331 int isPCinFlow(pCode *pc, pCode *pcflow)
4337 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4340 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4346 /*-----------------------------------------------------------------*/
4347 /*-----------------------------------------------------------------*/
4349 static void BanksUsedFlow2(pCode *pcflow)
4358 if(!isPCFL(pcflow)) {
4359 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4363 pc = findNextInstruction(pcflow->next);
4365 PCFL(pcflow)->lastBank = -1;
4367 while(isPCinFlow(pc,pcflow)) {
4369 int bank_selected = isBankInstruction(pc);
4371 //if(PCI(pc)->pcflow)
4372 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4374 if(bank_selected > 0) {
4375 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4377 // This instruction is modifying banking bits before accessing registers
4379 PCFL(pcflow)->firstBank = -1;
4381 if(PCFL(pcflow)->lastBank == -1)
4382 PCFL(pcflow)->lastBank = 0;
4384 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4385 if(bank_selected & SET_BANK_BIT)
4386 PCFL(pcflow)->lastBank |= bank;
4390 reg = getRegFromInstruction(pc);
4392 if(reg && !isREGinBank(reg, bank)) {
4393 int allbanks = REGallBanks(reg);
4395 PCFL(pcflow)->firstBank = allbanks;
4397 PCFL(pcflow)->lastBank = allbanks;
4404 pc = findNextInstruction(pc->next);
4407 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4408 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4411 /*-----------------------------------------------------------------*/
4412 /*-----------------------------------------------------------------*/
4414 static void BanksUsedFlow(pBlock *pb)
4419 //pb->pcHead->print(stderr, pb->pcHead);
4421 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4422 //pcflow->print(stderr,pcflow);
4424 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4426 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4428 BanksUsedFlow2(pcflow);
4434 /*-----------------------------------------------------------------*/
4435 /* Inserts a new pCodeInstruction before an existing one */
4436 /*-----------------------------------------------------------------*/
4437 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4440 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4442 /* Move the label, if there is one */
4445 new_pci->label = pci->label;
4449 /* Move the C code comment, if there is one */
4452 new_pci->cline = pci->cline;
4456 /* The new instruction has the same pcflow block */
4457 new_pci->pcflow = pci->pcflow;
4461 /*-----------------------------------------------------------------*/
4462 /*-----------------------------------------------------------------*/
4463 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4467 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4469 insertPCodeInstruction(pci, PCI(new_pc));
4472 /*-----------------------------------------------------------------*/
4473 /*-----------------------------------------------------------------*/
4474 static void insertBankSel(pCodeInstruction *pci, const char *name)
4478 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4479 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4480 if (pcop->name == 0)
4481 pcop->name = strdup(name);
4482 new_pc = newpCode(POC_BANKSEL, pcop);
4484 insertPCodeInstruction(pci, PCI(new_pc));
4487 /*-----------------------------------------------------------------*/
4488 /* If the register is a fixed known addess then we can assign the */
4489 /* bank selection bits. Otherwise the linker is going to assign */
4490 /* the register location and thus has to set bank selection bits */
4491 /* through the banksel directive. */
4492 /* One critical assumption here is that within this C module all */
4493 /* the locally allocated registers are in the same udata sector. */
4494 /* Therefore banksel is only called for external registers or the */
4495 /* first time a local register is encountered. */
4496 /*-----------------------------------------------------------------*/
4497 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4498 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4501 int a = reg->alias>>7;
4503 return cur_bank; // This register is available in all banks
4504 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4505 return cur_bank; // This register is available in banks 0 & 1
4507 if (reg->address&0x80) {
4508 if ((cur_bank==1)||(cur_bank==3)) {
4509 return cur_bank; // This register is available in banks 1 & 3
4512 if ((cur_bank==0)||(cur_bank==1)) {
4513 return cur_bank; // This register is available in banks 0 & 2
4518 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4520 LastRegIdx = reg->rIdx;
4523 bank = REG_BANK(reg);
4524 } else if (reg->isExtern) {
4525 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4527 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4529 if ((cur_bank == 'L')&&(bank == 'L')) { // If current bank and new bank are both allocated locally by the linker, then assume it is in same bank.
4530 return 'L'; // Local registers are presumed to be in same linker assigned bank
4531 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4532 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4533 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4534 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4535 } else if ((cur_bank == -1)||(cur_bank == 'L')||(cur_bank == 'E')) { // Current bank unknown and new register bank is known then can set bank bits
4536 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4537 if (getMaxRam()&0x100)
4538 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4539 } else { // Current bank and new register banks known - can set bank bits
4540 switch((cur_bank^bank) & 3) {
4544 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4547 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4550 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4551 if (getMaxRam()&0x100)
4552 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4560 /*-----------------------------------------------------------------*/
4561 /* Check for bank selection pcodes instructions and modify */
4562 /* cur_bank to match. */
4563 /*-----------------------------------------------------------------*/
4564 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4566 if (isSTATUS_REG(reg)) {
4568 if (PCI(pc)->op == POC_BCF) {
4569 int old_bank = *cur_bank;
4570 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4571 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4572 if (*cur_bank & ~(0x3))
4575 *cur_bank = *cur_bank&0x2;
4576 LastRegIdx = reg->rIdx;
4577 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4578 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4579 if (*cur_bank & ~(0x3))
4582 *cur_bank = *cur_bank&0x1;
4583 LastRegIdx = reg->rIdx;
4585 return old_bank != *cur_bank;
4588 if (PCI(pc)->op == POC_BSF) {
4589 int old_bank = *cur_bank;
4590 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4591 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4592 if (*cur_bank & ~(0x3))
4595 *cur_bank = (*cur_bank&0x2) | 0x1;
4596 LastRegIdx = reg->rIdx;
4597 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4598 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4599 if (*cur_bank & ~(0x3))
4602 *cur_bank = (*cur_bank&0x1) | 0x2;
4603 LastRegIdx = reg->rIdx;
4605 return old_bank != *cur_bank;
4608 } else if (PCI(pc)->op == POC_BANKSEL) {
4609 int old_bank = *cur_bank;
4610 regs *r = PCOR(PCI(pc)->pcop)->r;
4611 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4612 LastRegIdx = reg->rIdx;
4613 return old_bank != *cur_bank;
4619 /*-----------------------------------------------------------------*/
4620 /* Set bank selection if necessary */
4621 /*-----------------------------------------------------------------*/
4622 static int DoBankSelect(pCode *pc, int cur_bank) {
4630 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4631 if (pcf && isPCF(pcf)) {
4633 int rbank = 'U'; // Undetermined
4634 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4635 // Check all the returns to work out what bank is selected
4636 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4638 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4640 rbank = PCFL(pcfr)->lastBank;
4642 if (rbank != PCFL(pcfr)->lastBank)
4643 return -1; // Unknown bank - multiple returns with different banks
4648 return -1; // Unknown bank
4650 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4651 /* Extern functions may use registers in different bank - must call banksel */
4652 return -1; /* Unknown bank */
4656 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4657 return -1; /* New bank unknown - linkers choice. */
4660 reg = getRegFromInstruction(pc);
4662 if (IsBankChange(pc,reg,&cur_bank))
4664 if (!isPCI_LIT(pc)) {
4666 /* Examine the instruction before this one to make sure it is
4667 * not a skip type instruction */
4668 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4670 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4671 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4673 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4675 if (!PCI(pc)->pcflow)
4676 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4678 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4684 /*-----------------------------------------------------------------*/
4685 /*-----------------------------------------------------------------*/
4687 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4695 pc = findNextInstruction(pcfl->pc.next);
4697 while(isPCinFlow(pc,PCODE(pcfl))) {
4699 cur_bank = DoBankSelect(pc,cur_bank);
4701 pc = findNextInstruction(pc->next);
4705 if(pcprev && cur_bank) {
4706 // Set bank state to unknown at the end of each flow block
4712 /*-----------------------------------------------------------------*/
4713 /*int compareBankFlow - compare the banking requirements between */
4715 /*-----------------------------------------------------------------*/
4717 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4720 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4723 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4726 if(pcflow->firstBank == -1)
4730 if(pcflowLink->pcflow->firstBank == -1) {
4731 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4732 pcflowLink->pcflow->to :
4733 pcflowLink->pcflow->from);
4734 return compareBankFlow(pcflow, pctl, toORfrom);
4738 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4741 pcflowLink->bank_conflict++;
4742 pcflowLink->pcflow->FromConflicts++;
4743 pcflow->ToConflicts++;
4746 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4749 pcflowLink->bank_conflict++;
4750 pcflowLink->pcflow->ToConflicts++;
4751 pcflow->FromConflicts++;
4755 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4756 pcflowLink->pcflow->pc.seq,
4757 pcflowLink->pcflow->FromConflicts,
4758 pcflowLink->pcflow->ToConflicts);
4764 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4767 void FixBankFlow(pBlock *pb)
4771 pCodeFlowLink *pcfl;
4773 pCode *pcflow_max_To=NULL;
4774 pCode *pcflow_max_From=NULL;
4775 int max_ToConflicts=0;
4776 int max_FromConflicts=0;
4778 /fprintf(stderr,"Fix Bank flow \n");
4779 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4783 First loop through all of the flow objects in this pcode block
4784 and fix the ones that have banking conflicts between the
4788 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4790 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4792 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4794 if(!isPCFL(pcflow)) {
4795 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4799 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4800 PCFL(pcflow)->firstBank >= 0 &&
4801 PCFL(pcflow)->lastBank >= 0 ) {
4803 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4804 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4806 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4807 BanksUsedFlow2(pcflow);
4812 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4814 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4816 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4821 if(!isPCFL(pcflow)) {
4822 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4826 PCFL(pcflow)->FromConflicts = 0;
4827 PCFL(pcflow)->ToConflicts = 0;
4832 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4833 pcfl = setFirstItem(PCFL(pcflow)->from);
4836 pc = PCODE(pcfl->pcflow);
4839 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4840 pc->print(stderr,pc);
4843 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4846 pcfl=setNextItem(PCFL(pcflow)->from);
4849 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4850 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4852 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4853 BanksUsedFlow2(pcflow);
4855 continue; / * Don't need to check the flow from here - it's already been fixed * /
4862 pcfl = setFirstItem(PCFL(pcflow)->to);
4865 pc = PCODE(pcfl->pcflow);
4867 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4868 pc->print(stderr,pc);
4871 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4874 pcfl=setNextItem(PCFL(pcflow)->to);
4877 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4878 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4880 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4881 BanksUsedFlow2(pcflow);
4886 Loop through the flow objects again and find the ones with the
4890 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4892 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4894 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4895 pcflow_max_To = pcflow;
4897 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4898 pcflow_max_From = pcflow;
4902 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4903 PCFL(pcflow_max_To)->pc.seq,
4904 PCFL(pcflow_max_To)->ToConflicts);
4907 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4908 PCFL(pcflow_max_From)->pc.seq,
4909 PCFL(pcflow_max_From)->FromConflicts);
4914 /*-----------------------------------------------------------------*/
4915 /*-----------------------------------------------------------------*/
4916 void DumpFlow(pBlock *pb)
4920 pCodeFlowLink *pcfl;
4923 fprintf(stderr,"Dump flow \n");
4924 pb->pcHead->print(stderr, pb->pcHead);
4926 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4927 pcflow->print(stderr,pcflow);
4929 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4931 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4933 if(!isPCFL(pcflow)) {
4934 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4937 fprintf(stderr,"dumping: ");
4938 pcflow->print(stderr,pcflow);
4939 FlowStats(PCFL(pcflow));
4941 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4943 pc = PCODE(pcfl->pcflow);
4945 fprintf(stderr, " from seq %d:\n",pc->seq);
4947 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4948 pc->print(stderr,pc);
4953 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4955 pc = PCODE(pcfl->pcflow);
4957 fprintf(stderr, " to seq %d:\n",pc->seq);
4959 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4960 pc->print(stderr,pc);
4969 /*-----------------------------------------------------------------*/
4970 /*-----------------------------------------------------------------*/
4971 int OptimizepBlock(pBlock *pb)
4976 if(!pb || !peepOptimizing)
4979 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4981 for(pc = pb->pcHead; pc; pc = pc->next)
4982 matches += pCodePeepMatchRule(pc);
4985 pc = findNextInstruction(pb->pcHead);
4993 if(pCodePeepMatchRule(pc)) {
4998 pc = findNextInstruction(pcprev->next);
5000 pc = findNextInstruction(pb->pcHead);
5002 pc = findNextInstruction(pc->next);
5006 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5011 /*-----------------------------------------------------------------*/
5012 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5013 /*-----------------------------------------------------------------*/
5014 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5018 for(pc = pcs; pc; pc = pc->next) {
5020 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5022 (PCI(pc)->pcop->type == PO_LABEL) &&
5023 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5030 /*-----------------------------------------------------------------*/
5031 /*-----------------------------------------------------------------*/
5032 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5039 (PCI(pc)->pcop->type == PO_LABEL)) {
5041 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5043 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5045 free(pcol->pcop.name);
5047 /* If the key is negative, then we (probably) have a label to
5048 * a function and the name is already defined */
5051 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5055 //sprintf(buffer,"_%05d_DS_",pcl->key);
5057 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5059 pcol->pcop.name = Safe_strdup(s);
5060 pcol->key = pcl->key;
5061 //pc->print(stderr,pc);
5068 /*-----------------------------------------------------------------*/
5069 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5070 /* pCode chain if they're not used. */
5071 /*-----------------------------------------------------------------*/
5072 void pBlockRemoveUnusedLabels(pBlock *pb)
5074 pCode *pc; pCodeLabel *pcl;
5079 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5081 pBranch *pbr = PCI(pc)->label;
5082 if(pbr && pbr->next) {
5083 pCode *pcd = pb->pcHead;
5085 //fprintf(stderr, "multiple labels\n");
5086 //pc->print(stderr,pc);
5091 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5092 //fprintf(stderr,"Used by:\n");
5093 //pcd->print(stderr,pcd);
5095 exchangeLabels(PCL(pbr->pc),pcd);
5104 for(pc = pb->pcHead; pc; pc = pc->next) {
5106 if(isPCL(pc)) // Label pcode
5108 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5109 pcl = PCL(PCI(pc)->label->pc);
5112 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5114 /* This pCode is a label, so search the pBlock to see if anyone
5117 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5118 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5119 /* Couldn't find an instruction that refers to this label
5120 * So, unlink the pCode label from it's pCode chain
5121 * and destroy the label */
5122 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5124 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5125 if(pc->type == PC_LABEL) {
5127 pCodeLabelDestruct(pc);
5129 unlinkpCodeFromBranch(pc, PCODE(pcl));
5130 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5141 /*-----------------------------------------------------------------*/
5142 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5143 /* chain and put them into pBranches that are */
5144 /* associated with the appropriate pCode */
5146 /*-----------------------------------------------------------------*/
5147 void pBlockMergeLabels(pBlock *pb)
5150 pCode *pc, *pcnext=NULL;
5155 /* First, Try to remove any unused labels */
5156 //pBlockRemoveUnusedLabels(pb);
5158 /* Now loop through the pBlock and merge the labels with the opcodes */
5161 // for(pc = pb->pcHead; pc; pc = pc->next) {
5164 pCode *pcn = pc->next;
5166 if(pc->type == PC_LABEL) {
5168 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5169 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5170 if((pcnext = findNextInstruction(pc) )) {
5172 // Unlink the pCode label from it's pCode chain
5175 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5176 // And link it into the instruction's pBranch labels. (Note, since
5177 // it's possible to have multiple labels associated with one instruction
5178 // we must provide a means to accomodate the additional labels. Thus
5179 // the labels are placed into the singly-linked list "label" as
5180 // opposed to being a single member of the pCodeInstruction.)
5182 //_ALLOC(pbr,sizeof(pBranch));
5183 pbr = Safe_calloc(1,sizeof(pBranch));
5187 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5190 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5192 } else if(pc->type == PC_CSOURCE) {
5194 /* merge the source line symbolic info into the next instruction */
5195 if((pcnext = findNextInstruction(pc) )) {
5197 // Unlink the pCode label from it's pCode chain
5199 PCI(pcnext)->cline = PCCS(pc);
5200 //fprintf(stderr, "merging CSRC\n");
5201 //genericPrint(stderr,pcnext);
5207 pBlockRemoveUnusedLabels(pb);
5211 /*-----------------------------------------------------------------*/
5212 /*-----------------------------------------------------------------*/
5213 int OptimizepCode(char dbName)
5215 #define MAX_PASSES 4
5224 DFPRINTF((stderr," Optimizing pCode\n"));
5228 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5229 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5230 matches += OptimizepBlock(pb);
5233 while(matches && ++passes < MAX_PASSES);
5238 /*-----------------------------------------------------------------*/
5239 /* popCopyGPR2Bit - copy a pcode operator */
5240 /*-----------------------------------------------------------------*/
5242 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5246 pcop = newpCodeOpBit(pc->name, bitval, 0);
5248 if( !( (pcop->type == PO_LABEL) ||
5249 (pcop->type == PO_LITERAL) ||
5250 (pcop->type == PO_STR) ))
5251 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5257 /*-----------------------------------------------------------------*/
5258 /*-----------------------------------------------------------------*/
5259 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5262 int firstBank = 'U';
5267 for (pc=pb->pcHead; pc; pc=pc->next) {
5269 firstBank = PCFL(pc)->firstBank;
5273 if (firstBank != 'U') {
5274 /* This block has already been done */
5275 if (firstBank != cur_bank) {
5276 /* This block has started with a different bank - must adjust it */
5277 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5280 regs *reg = getRegFromInstruction(pc);
5282 DoBankSelect(pc,cur_bank);
5292 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5295 for (pc=pb->pcHead; pc; pc=pc->next) {
5297 PCFL(pc)->firstBank = cur_bank;
5300 cur_bank = DoBankSelect(pc,cur_bank);
5303 /* Trace through branches and set the bank selection as required. */
5306 for (pc=pb->pcHead; pc; pc=pc->next) {
5308 PCFL(pc)->firstBank = cur_bank;
5312 if (PCI(pc)->op == POC_GOTO) {
5313 int lastRegIdx = LastRegIdx;
5315 /* Trace through branch */
5316 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5319 regs *reg = getRegFromInstruction(pcl);
5321 int bankUnknown = -1;
5322 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5324 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5330 LastRegIdx = lastRegIdx;
5332 /* Keep track out current bank */
5333 regs *reg = getRegFromInstruction(pc);
5335 IsBankChange(pc,reg,&cur_bank);
5342 /*-----------------------------------------------------------------*/
5343 /*-----------------------------------------------------------------*/
5344 void pBlockDestruct(pBlock *pb)
5355 /*-----------------------------------------------------------------*/
5356 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5357 /* name dbName and combine them */
5358 /* into one block */
5359 /*-----------------------------------------------------------------*/
5360 void mergepBlocks(char dbName)
5363 pBlock *pb, *pbmerged = NULL,*pbn;
5365 pb = the_pFile->pbHead;
5367 //fprintf(stderr," merging blocks named %c\n",dbName);
5371 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5372 if( getpBlock_dbName(pb) == dbName) {
5374 //fprintf(stderr," merged block %c\n",dbName);
5379 addpCode2pBlock(pbmerged, pb->pcHead);
5380 /* addpCode2pBlock doesn't handle the tail: */
5381 pbmerged->pcTail = pb->pcTail;
5383 pb->prev->next = pbn;
5385 pbn->prev = pb->prev;
5390 //printpBlock(stderr, pbmerged);
5397 /*-----------------------------------------------------------------*/
5398 /* AnalyzeFlow - Examine the flow of the code and optimize */
5400 /* level 0 == minimal optimization */
5401 /* optimize registers that are used only by two instructions */
5402 /* level 1 == maximal optimization */
5403 /* optimize by looking at pairs of instructions that use the */
5405 /*-----------------------------------------------------------------*/
5407 void AnalyzeFlow(int level)
5409 static int times_called=0;
5417 /* if this is not the first time this function has been called,
5418 then clean up old flow information */
5419 if(times_called++) {
5420 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5423 RegsUnMapLiveRanges();
5429 /* Phase 2 - Flow Analysis - Register Banking
5431 * In this phase, the individual flow blocks are examined
5432 * and register banking is fixed.
5435 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5436 //FixRegisterBanking(pb);
5438 /* Phase 2 - Flow Analysis
5440 * In this phase, the pCode is partition into pCodeFlow
5441 * blocks. The flow blocks mark the points where a continuous
5442 * stream of instructions changes flow (e.g. because of
5443 * a call or goto or whatever).
5446 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5450 /* Phase 2 - Flow Analysis - linking flow blocks
5452 * In this phase, the individual flow blocks are examined
5453 * to determine their order of excution.
5456 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5459 /* Phase 3 - Flow Analysis - Flow Tree
5461 * In this phase, the individual flow blocks are examined
5462 * to determine their order of excution.
5465 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5469 /* Phase x - Flow Analysis - Used Banks
5471 * In this phase, the individual flow blocks are examined
5472 * to determine the Register Banks they use
5475 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5479 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5480 pCodeRegMapLiveRanges(pb);
5482 RemoveUnusedRegisters();
5484 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5485 pCodeRegOptimizeRegUsage(level);
5491 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5496 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5498 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5499 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5500 pcflow = pcflow->next) {
5502 FillFlow(PCFL(pcflow));
5507 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5509 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5510 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5511 pcflow = pcflow->next) {
5513 FlowStats(PCFL(pcflow));
5519 /*-----------------------------------------------------------------*/
5520 /* AnalyzeBanking - Called after the memory addresses have been */
5521 /* assigned to the registers. */
5523 /*-----------------------------------------------------------------*/
5525 void AnalyzeBanking(void)
5529 if(!picIsInitialized()) {
5530 setDefMaxRam(); // Max RAM has not been included, so use default setting
5533 /* Phase x - Flow Analysis - Used Banks
5535 * In this phase, the individual flow blocks are examined
5536 * to determine the Register Banks they use
5542 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5543 // BanksUsedFlow(pb);
5544 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5545 FixRegisterBanking(pb,-1); // cur_bank is unknown
5549 /*-----------------------------------------------------------------*/
5550 /*-----------------------------------------------------------------*/
5551 DEFSETFUNC (resetrIdx)
5553 regs *r = (regs *)item;
5561 /*-----------------------------------------------------------------*/
5562 /* InitRegReuse - Initialises variables for code analyzer */
5563 /*-----------------------------------------------------------------*/
5565 void InitReuseReg(void)
5567 /* Find end of statically allocated variables for start idx */
5568 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5570 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5571 if (r->type != REG_SFR) {
5572 maxIdx += r->size; /* Increment for all statically allocated variables */
5576 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5579 /*-----------------------------------------------------------------*/
5580 /*-----------------------------------------------------------------*/
5581 static unsigned register_reassign(pBlock *pb, unsigned idx)
5585 /* check recursion */
5586 pc = setFirstItem(pb->function_entries);
5592 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5594 if (pb->tregisters) {
5596 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5597 if (r->type == REG_GPR) {
5599 if (r->rIdx < (int)idx) {
5602 if (peakIdx < idx) peakIdx = idx;
5603 sprintf(s,"r0x%02X", r->rIdx);
5604 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5606 r->name = Safe_strdup(s);
5612 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5614 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5615 char *dest = get_op_from_instruction(PCI(pc));
5617 pCode *pcn = findFunction(dest);
5619 register_reassign(pcn->pb,idx);
5628 /*------------------------------------------------------------------*/
5629 /* ReuseReg were call tree permits */
5631 /* Re-allocate the GPR for optimum reuse for a given pblock */
5632 /* eg if a function m() calls function f1() and f2(), where f1 */
5633 /* allocates a local variable vf1 and f2 allocates a local */
5634 /* variable vf2. Then providing f1 and f2 do not call each other */
5635 /* they may share the same general purpose registers for vf1 and */
5637 /* This is done by first setting the the regs rIdx to start after */
5638 /* all the global variables, then walking through the call tree */
5639 /* renaming the registers to match their new idx and incrementng */
5640 /* it as it goes. If a function has already been called it will */
5641 /* only rename the registers if it has already used up those */
5642 /* registers ie rIdx of the function's registers is lower than the */
5643 /* current rIdx. That way the register will not be reused while */
5644 /* still being used by an eariler function call. */
5646 /* Note for this to work the functions need to be declared static. */
5648 /*------------------------------------------------------------------*/
5653 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5654 /* Non static functions can be called from other modules so their registers must reassign */
5655 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5656 register_reassign(pb,peakIdx);
5660 /*-----------------------------------------------------------------*/
5661 /* buildCallTree - look at the flow and extract all of the calls */
5663 /*-----------------------------------------------------------------*/
5665 void buildCallTree(void )
5674 /* Now build the call tree.
5675 First we examine all of the pCodes for functions.
5676 Keep in mind that the function boundaries coincide
5677 with pBlock boundaries.
5679 The algorithm goes something like this:
5680 We have two nested loops. The outer loop iterates
5681 through all of the pBlocks/functions. The inner
5682 loop iterates through all of the pCodes for
5683 a given pBlock. When we begin iterating through
5684 a pBlock, the variable pc_fstart, pCode of the start
5685 of a function, is cleared. We then search for pCodes
5686 of type PC_FUNCTION. When one is encountered, we
5687 initialize pc_fstart to this and at the same time
5688 associate a new pBranch object that signifies a
5689 branch entry. If a return is found, then this signifies
5690 a function exit point. We'll link the pCodes of these
5691 returns to the matching pc_fstart.
5693 When we're done, a doubly linked list of pBranches
5694 will exist. The head of this list is stored in
5695 `the_pFile', which is the meta structure for all
5696 of the pCode. Look at the printCallTree function
5697 on how the pBranches are linked together.
5700 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5701 pCode *pc_fstart=NULL;
5702 for(pc = pb->pcHead; pc; pc = pc->next) {
5704 pCodeFunction *pcf = PCF(pc);
5707 if(STRCASECMP(pcf->fname, "_main") == 0) {
5708 //fprintf(stderr," found main \n");
5709 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5713 pbr = Safe_calloc(1,sizeof(pBranch));
5714 pbr->pc = pc_fstart = pc;
5717 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5719 // Here's a better way of doing the same:
5720 addSet(&pb->function_entries, pc);
5723 // Found an exit point in a function, e.g. return
5724 // (Note, there may be more than one return per function)
5726 pBranchLink(PCF(pc_fstart), pcf);
5728 addSet(&pb->function_exits, pc);
5730 } else if(isCALL(pc)) {
5731 addSet(&pb->function_calls,pc);
5737 /*-----------------------------------------------------------------*/
5738 /* AnalyzepCode - parse the pCode that has been generated and form */
5739 /* all of the logical connections. */
5741 /* Essentially what's done here is that the pCode flow is */
5743 /*-----------------------------------------------------------------*/
5745 void AnalyzepCode(char dbName)
5756 /* Phase 1 - Register allocation and peep hole optimization
5758 * The first part of the analysis is to determine the registers
5759 * that are used in the pCode. Once that is done, the peep rules
5760 * are applied to the code. We continue to loop until no more
5761 * peep rule optimizations are found (or until we exceed the
5762 * MAX_PASSES threshold).
5764 * When done, the required registers will be determined.
5770 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5772 /* First, merge the labels with the instructions */
5773 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5774 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5776 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5777 pBlockMergeLabels(pb);
5780 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5784 changes = OptimizepCode(dbName);
5786 } while(changes && (i++ < MAX_PASSES));
5791 /*-----------------------------------------------------------------*/
5792 /* ispCodeFunction - returns true if *pc is the pCode of a */
5794 /*-----------------------------------------------------------------*/
5795 bool ispCodeFunction(pCode *pc)
5798 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5804 /*-----------------------------------------------------------------*/
5805 /* findFunction - Search for a function by name (given the name) */
5806 /* in the set of all functions that are in a pBlock */
5807 /* (note - I expect this to change because I'm planning to limit */
5808 /* pBlock's to just one function declaration */
5809 /*-----------------------------------------------------------------*/
5810 pCode *findFunction(char *fname)
5817 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5819 pc = setFirstItem(pb->function_entries);
5822 if((pc->type == PC_FUNCTION) &&
5824 (strcmp(fname, PCF(pc)->fname)==0))
5827 pc = setNextItem(pb->function_entries);
5835 void MarkUsedRegisters(set *regset)
5840 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5841 r2 = pic14_regWithIdx(r1->rIdx);
5849 void pBlockStats(FILE *of, pBlock *pb)
5855 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5857 // for now just print the first element of each set
5858 pc = setFirstItem(pb->function_entries);
5860 fprintf(of,";entry: ");
5863 pc = setFirstItem(pb->function_exits);
5865 fprintf(of,";has an exit\n");
5869 pc = setFirstItem(pb->function_calls);
5871 fprintf(of,";functions called:\n");
5874 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5875 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5877 pc = setNextItem(pb->function_calls);
5881 r = setFirstItem(pb->tregisters);
5883 int n = elementsInSet(pb->tregisters);
5885 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5888 fprintf(of,"; %s\n",r->name);
5889 r = setNextItem(pb->tregisters);
5894 /*-----------------------------------------------------------------*/
5895 /*-----------------------------------------------------------------*/
5897 static void sequencepCode(void)
5903 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5905 pb->seq = GpCodeSequenceNumber+1;
5907 for( pc = pb->pcHead; pc; pc = pc->next)
5908 pc->seq = ++GpCodeSequenceNumber;
5914 /*-----------------------------------------------------------------*/
5915 /*-----------------------------------------------------------------*/
5917 set *register_usage(pBlock *pb)
5920 set *registers=NULL;
5921 set *registersInCallPath = NULL;
5923 / * check recursion * /
5925 pc = setFirstItem(pb->function_entries);
5932 if(pc->type != PC_FUNCTION)
5933 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5935 pc = setFirstItem(pb->function_calls);
5936 for( ; pc; pc = setNextItem(pb->function_calls)) {
5938 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5939 char *dest = get_op_from_instruction(PCI(pc));
5941 pcn = findFunction(dest);
5943 registersInCallPath = register_usage(pcn->pb);
5945 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5950 pBlockStats(stderr,pb); // debug
5953 // Mark the registers in this block as used.
5955 MarkUsedRegisters(pb->tregisters);
5956 if(registersInCallPath) {
5957 / * registers were used in the functions this pBlock has called * /
5958 / * so now, we need to see if these collide with the ones we are * /
5961 regs *r1,*r2, *newreg;
5963 DFPRINTF((stderr,"comparing registers\n"));
5965 r1 = setFirstItem(registersInCallPath);
5967 if (r1->type != REG_STK) {
5968 r2 = setFirstItem(pb->tregisters);
5970 while(r2 && (r2->type != REG_STK)) {
5972 if(r2->rIdx == r1->rIdx) {
5973 newreg = pic14_findFreeReg(REG_GPR);
5977 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5981 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5982 r1->rIdx, newreg->rIdx));
5983 r2->rIdx = newreg->rIdx;
5985 r2->name = Safe_strdup(newreg->name);
5989 newreg->wasUsed = 1;
5991 r2 = setNextItem(pb->tregisters);
5995 r1 = setNextItem(registersInCallPath);
5998 / * Collisions have been resolved. Now free the registers in the call path * /
5999 r1 = setFirstItem(registersInCallPath);
6001 newreg = pic14_regWithIdx(r1->rIdx);
6002 if (newreg) newreg->isFree = 1;
6003 r1 = setNextItem(registersInCallPath);
6007 // MarkUsedRegisters(pb->registers);
6009 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6012 DFPRINTF((stderr,"returning regs\n"));
6014 DFPRINTF((stderr,"not returning regs\n"));
6016 DFPRINTF((stderr,"pBlock after register optim.\n"));
6017 pBlockStats(stderr,pb); // debug
6024 /*-----------------------------------------------------------------*/
6025 /* printCallTree - writes the call tree to a file */
6027 /*-----------------------------------------------------------------*/
6028 void pct2(FILE *of,pBlock *pb,int indent)
6032 // set *registersInCallPath = NULL;
6038 return; //recursion ?
6040 pc = setFirstItem(pb->function_entries);
6047 for(i=0;i<indent;i++) // Indentation
6050 if(pc->type == PC_FUNCTION)
6051 fprintf(of,"%s\n",PCF(pc)->fname);
6056 pc = setFirstItem(pb->function_calls);
6057 for( ; pc; pc = setNextItem(pb->function_calls)) {
6059 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6060 char *dest = get_op_from_instruction(PCI(pc));
6062 pcn = findFunction(dest);
6064 pct2(of,pcn->pb,indent+1);
6066 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6074 /*-----------------------------------------------------------------*/
6075 /* printCallTree - writes the call tree to a file */
6077 /*-----------------------------------------------------------------*/
6079 void printCallTree(FILE *of)
6091 fprintf(of, "\npBlock statistics\n");
6092 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6097 fprintf(of,"Call Tree\n");
6098 pbr = the_pFile->functions;
6102 if(!ispCodeFunction(pc))
6103 fprintf(of,"bug in call tree");
6106 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6108 while(pc->next && !ispCodeFunction(pc->next)) {
6110 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6111 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6119 fprintf(of,"\n**************\n\na better call tree\n");
6120 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6125 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6126 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6132 /*-----------------------------------------------------------------*/
6134 /*-----------------------------------------------------------------*/
6136 void InlineFunction(pBlock *pb)
6144 pc = setFirstItem(pb->function_calls);
6146 for( ; pc; pc = setNextItem(pb->function_calls)) {
6149 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6150 pCode *pcp = pc->prev;
6156 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 */
6158 InlineFunction(pcn->pb);
6161 At this point, *pc points to a CALL mnemonic, and
6162 *pcn points to the function that is being called.
6164 To in-line this call, we need to remove the CALL
6165 and RETURN(s), and link the function pCode in with
6172 /* Check if previous instruction was a bit skip */
6173 if (isPCI_BITSKIP(pcp)) {
6175 /* Invert skip instruction and add a goto */
6176 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6178 if(isPCL(pc_call->next)) { // Label pcode
6179 pcl = PCL(pc_call->next);
6180 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6181 pcl = PCL(PCI(pc_call->next)->label->pc);
6183 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6184 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6186 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6189 /* remove callee pBlock from the pBlock linked list */
6190 removepBlock(pcn->pb);
6198 /* Remove the Function pCode */
6199 pct = findNextInstruction(pcn->next);
6201 /* Link the function with the callee */
6202 if (pcp) pcp->next = pcn->next;
6203 pcn->next->prev = pcp;
6205 /* Convert the function name into a label */
6207 pbr = Safe_calloc(1,sizeof(pBranch));
6208 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6210 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6211 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6213 /* turn all of the return's except the last into goto's */
6214 /* check case for 2 instruction pBlocks */
6215 pce = findNextInstruction(pcn->next);
6217 pCode *pce_next = findNextInstruction(pce->next);
6219 if(pce_next == NULL) {
6220 /* found the last return */
6221 pCode *pc_call_next = findNextInstruction(pc_call->next);
6223 //fprintf(stderr,"found last return\n");
6224 //pce->print(stderr,pce);
6225 pce->prev->next = pc_call->next;
6226 pc_call->next->prev = pce->prev;
6227 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6236 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6242 /*-----------------------------------------------------------------*/
6244 /*-----------------------------------------------------------------*/
6246 void InlinepCode(void)
6255 if(!functionInlining)
6258 /* Loop through all of the function definitions and count the
6259 * number of times each one is called */
6260 //fprintf(stderr,"inlining %d\n",__LINE__);
6262 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6264 pc = setFirstItem(pb->function_calls);
6266 for( ; pc; pc = setNextItem(pb->function_calls)) {
6269 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6270 if(pcn && isPCF(pcn)) {
6271 PCF(pcn)->ncalled++;
6274 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6279 //fprintf(stderr,"inlining %d\n",__LINE__);
6281 /* Now, Loop through the function definitions again, but this
6282 * time inline those functions that have only been called once. */
6284 InlineFunction(the_pFile->pbHead);
6285 //fprintf(stderr,"inlining %d\n",__LINE__);
6287 for(pb = the_pFile->pbHead; pb; pb = pb->next)