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
4519 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4521 LastRegIdx = reg->rIdx;
4525 bank = REG_BANK(reg);
4526 } else if (reg->isExtern) {
4527 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4529 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4531 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.
4532 return 'L'; // Local registers are presumed to be in same linker assigned bank
4533 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4534 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4535 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4536 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4537 } 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
4538 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4539 if (getMaxRam()&0x100)
4540 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4541 } else { // Current bank and new register banks known - can set bank bits
4542 switch((cur_bank^bank) & 3) {
4546 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4549 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4552 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4553 if (getMaxRam()&0x100)
4554 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4562 /*-----------------------------------------------------------------*/
4563 /* Check for bank selection pcodes instructions and modify */
4564 /* cur_bank to match. */
4565 /*-----------------------------------------------------------------*/
4566 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4568 if (isSTATUS_REG(reg)) {
4570 if (PCI(pc)->op == POC_BCF) {
4571 int old_bank = *cur_bank;
4572 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4573 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4574 if (*cur_bank & ~(0x3))
4577 *cur_bank = *cur_bank&0x2;
4578 LastRegIdx = reg->rIdx;
4579 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4580 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4581 if (*cur_bank & ~(0x3))
4584 *cur_bank = *cur_bank&0x1;
4585 LastRegIdx = reg->rIdx;
4587 return old_bank != *cur_bank;
4590 if (PCI(pc)->op == POC_BSF) {
4591 int old_bank = *cur_bank;
4592 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4593 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4594 if (*cur_bank & ~(0x3))
4597 *cur_bank = (*cur_bank&0x2) | 0x1;
4598 LastRegIdx = reg->rIdx;
4599 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4600 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4601 if (*cur_bank & ~(0x3))
4604 *cur_bank = (*cur_bank&0x1) | 0x2;
4605 LastRegIdx = reg->rIdx;
4607 return old_bank != *cur_bank;
4610 } else if (PCI(pc)->op == POC_BANKSEL) {
4611 int old_bank = *cur_bank;
4612 regs *r = PCOR(PCI(pc)->pcop)->r;
4613 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4614 LastRegIdx = reg->rIdx;
4615 return old_bank != *cur_bank;
4621 /*-----------------------------------------------------------------*/
4622 /* Set bank selection if necessary */
4623 /*-----------------------------------------------------------------*/
4624 static int DoBankSelect(pCode *pc, int cur_bank) {
4632 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4633 LastRegIdx = -1; /* do not know which register is touched in the called function... */
4634 if (pcf && isPCF(pcf)) {
4636 int rbank = 'U'; // Undetermined
4637 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4638 // Check all the returns to work out what bank is selected
4639 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4641 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4643 rbank = PCI(pcfr)->pcflow->lastBank;
4645 if (rbank != PCI(pcfr)->pcflow->lastBank)
4646 return -1; // Unknown bank - multiple returns with different banks
4651 return -1; // Unknown bank
4653 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4654 /* Extern functions may use registers in different bank - must call banksel */
4655 return -1; /* Unknown bank */
4661 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4662 return -1; /* New bank unknown - linkers choice. */
4665 reg = getRegFromInstruction(pc);
4667 if (IsBankChange(pc,reg,&cur_bank))
4669 if (!isPCI_LIT(pc)) {
4671 /* Examine the instruction before this one to make sure it is
4672 * not a skip type instruction */
4673 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4675 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4676 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4678 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4680 if (!PCI(pc)->pcflow)
4681 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4683 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4689 /*-----------------------------------------------------------------*/
4690 /*-----------------------------------------------------------------*/
4692 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4700 pc = findNextInstruction(pcfl->pc.next);
4702 while(isPCinFlow(pc,PCODE(pcfl))) {
4704 cur_bank = DoBankSelect(pc,cur_bank);
4706 pc = findNextInstruction(pc->next);
4710 if(pcprev && cur_bank) {
4711 // Set bank state to unknown at the end of each flow block
4717 /*-----------------------------------------------------------------*/
4718 /*int compareBankFlow - compare the banking requirements between */
4720 /*-----------------------------------------------------------------*/
4722 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4725 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4728 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4731 if(pcflow->firstBank == -1)
4735 if(pcflowLink->pcflow->firstBank == -1) {
4736 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4737 pcflowLink->pcflow->to :
4738 pcflowLink->pcflow->from);
4739 return compareBankFlow(pcflow, pctl, toORfrom);
4743 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4746 pcflowLink->bank_conflict++;
4747 pcflowLink->pcflow->FromConflicts++;
4748 pcflow->ToConflicts++;
4751 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4754 pcflowLink->bank_conflict++;
4755 pcflowLink->pcflow->ToConflicts++;
4756 pcflow->FromConflicts++;
4760 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4761 pcflowLink->pcflow->pc.seq,
4762 pcflowLink->pcflow->FromConflicts,
4763 pcflowLink->pcflow->ToConflicts);
4769 /*-----------------------------------------------------------------*/
4770 /*-----------------------------------------------------------------*/
4772 void FixBankFlow(pBlock *pb)
4776 pCodeFlowLink *pcfl;
4778 pCode *pcflow_max_To=NULL;
4779 pCode *pcflow_max_From=NULL;
4780 int max_ToConflicts=0;
4781 int max_FromConflicts=0;
4783 /fprintf(stderr,"Fix Bank flow \n");
4784 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4788 First loop through all of the flow objects in this pcode block
4789 and fix the ones that have banking conflicts between the
4793 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4795 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4797 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4799 if(!isPCFL(pcflow)) {
4800 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4804 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4805 PCFL(pcflow)->firstBank >= 0 &&
4806 PCFL(pcflow)->lastBank >= 0 ) {
4808 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4809 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4811 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4812 BanksUsedFlow2(pcflow);
4817 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4819 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4821 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4826 if(!isPCFL(pcflow)) {
4827 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4831 PCFL(pcflow)->FromConflicts = 0;
4832 PCFL(pcflow)->ToConflicts = 0;
4837 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4838 pcfl = setFirstItem(PCFL(pcflow)->from);
4841 pc = PCODE(pcfl->pcflow);
4844 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4845 pc->print(stderr,pc);
4848 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4851 pcfl=setNextItem(PCFL(pcflow)->from);
4854 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4855 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4857 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4858 BanksUsedFlow2(pcflow);
4860 continue; / * Don't need to check the flow from here - it's already been fixed * /
4867 pcfl = setFirstItem(PCFL(pcflow)->to);
4870 pc = PCODE(pcfl->pcflow);
4872 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4873 pc->print(stderr,pc);
4876 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4879 pcfl=setNextItem(PCFL(pcflow)->to);
4882 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4883 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4885 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4886 BanksUsedFlow2(pcflow);
4891 Loop through the flow objects again and find the ones with the
4895 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4897 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4899 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4900 pcflow_max_To = pcflow;
4902 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4903 pcflow_max_From = pcflow;
4907 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4908 PCFL(pcflow_max_To)->pc.seq,
4909 PCFL(pcflow_max_To)->ToConflicts);
4912 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4913 PCFL(pcflow_max_From)->pc.seq,
4914 PCFL(pcflow_max_From)->FromConflicts);
4919 /*-----------------------------------------------------------------*/
4920 /*-----------------------------------------------------------------*/
4921 void DumpFlow(pBlock *pb)
4925 pCodeFlowLink *pcfl;
4928 fprintf(stderr,"Dump flow \n");
4929 pb->pcHead->print(stderr, pb->pcHead);
4931 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4932 pcflow->print(stderr,pcflow);
4934 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4936 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4938 if(!isPCFL(pcflow)) {
4939 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4942 fprintf(stderr,"dumping: ");
4943 pcflow->print(stderr,pcflow);
4944 FlowStats(PCFL(pcflow));
4946 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4948 pc = PCODE(pcfl->pcflow);
4950 fprintf(stderr, " from seq %d:\n",pc->seq);
4952 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4953 pc->print(stderr,pc);
4958 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4960 pc = PCODE(pcfl->pcflow);
4962 fprintf(stderr, " to seq %d:\n",pc->seq);
4964 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4965 pc->print(stderr,pc);
4974 /*-----------------------------------------------------------------*/
4975 /*-----------------------------------------------------------------*/
4976 int OptimizepBlock(pBlock *pb)
4981 if(!pb || !peepOptimizing)
4984 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4986 for(pc = pb->pcHead; pc; pc = pc->next)
4987 matches += pCodePeepMatchRule(pc);
4990 pc = findNextInstruction(pb->pcHead);
4998 if(pCodePeepMatchRule(pc)) {
5003 pc = findNextInstruction(pcprev->next);
5005 pc = findNextInstruction(pb->pcHead);
5007 pc = findNextInstruction(pc->next);
5011 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5016 /*-----------------------------------------------------------------*/
5017 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5018 /*-----------------------------------------------------------------*/
5019 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5023 for(pc = pcs; pc; pc = pc->next) {
5025 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5027 (PCI(pc)->pcop->type == PO_LABEL) &&
5028 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5035 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5037 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5044 (PCI(pc)->pcop->type == PO_LABEL)) {
5046 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5048 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5050 free(pcol->pcop.name);
5052 /* If the key is negative, then we (probably) have a label to
5053 * a function and the name is already defined */
5056 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5060 //sprintf(buffer,"_%05d_DS_",pcl->key);
5062 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5064 pcol->pcop.name = Safe_strdup(s);
5065 pcol->key = pcl->key;
5066 //pc->print(stderr,pc);
5073 /*-----------------------------------------------------------------*/
5074 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5075 /* pCode chain if they're not used. */
5076 /*-----------------------------------------------------------------*/
5077 void pBlockRemoveUnusedLabels(pBlock *pb)
5079 pCode *pc; pCodeLabel *pcl;
5084 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5086 pBranch *pbr = PCI(pc)->label;
5087 if(pbr && pbr->next) {
5088 pCode *pcd = pb->pcHead;
5090 //fprintf(stderr, "multiple labels\n");
5091 //pc->print(stderr,pc);
5096 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5097 //fprintf(stderr,"Used by:\n");
5098 //pcd->print(stderr,pcd);
5100 exchangeLabels(PCL(pbr->pc),pcd);
5109 for(pc = pb->pcHead; pc; pc = pc->next) {
5111 if(isPCL(pc)) // Label pcode
5113 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5114 pcl = PCL(PCI(pc)->label->pc);
5117 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5119 /* This pCode is a label, so search the pBlock to see if anyone
5122 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5123 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5124 /* Couldn't find an instruction that refers to this label
5125 * So, unlink the pCode label from it's pCode chain
5126 * and destroy the label */
5127 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5129 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5130 if(pc->type == PC_LABEL) {
5132 pCodeLabelDestruct(pc);
5134 unlinkpCodeFromBranch(pc, PCODE(pcl));
5135 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5146 /*-----------------------------------------------------------------*/
5147 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5148 /* chain and put them into pBranches that are */
5149 /* associated with the appropriate pCode */
5151 /*-----------------------------------------------------------------*/
5152 void pBlockMergeLabels(pBlock *pb)
5155 pCode *pc, *pcnext=NULL;
5160 /* First, Try to remove any unused labels */
5161 //pBlockRemoveUnusedLabels(pb);
5163 /* Now loop through the pBlock and merge the labels with the opcodes */
5166 // for(pc = pb->pcHead; pc; pc = pc->next) {
5169 pCode *pcn = pc->next;
5171 if(pc->type == PC_LABEL) {
5173 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5174 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5175 if((pcnext = findNextInstruction(pc) )) {
5177 // Unlink the pCode label from it's pCode chain
5180 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5181 // And link it into the instruction's pBranch labels. (Note, since
5182 // it's possible to have multiple labels associated with one instruction
5183 // we must provide a means to accomodate the additional labels. Thus
5184 // the labels are placed into the singly-linked list "label" as
5185 // opposed to being a single member of the pCodeInstruction.)
5187 //_ALLOC(pbr,sizeof(pBranch));
5188 pbr = Safe_calloc(1,sizeof(pBranch));
5192 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5195 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5197 } else if(pc->type == PC_CSOURCE) {
5199 /* merge the source line symbolic info into the next instruction */
5200 if((pcnext = findNextInstruction(pc) )) {
5202 // Unlink the pCode label from it's pCode chain
5204 PCI(pcnext)->cline = PCCS(pc);
5205 //fprintf(stderr, "merging CSRC\n");
5206 //genericPrint(stderr,pcnext);
5212 pBlockRemoveUnusedLabels(pb);
5216 /*-----------------------------------------------------------------*/
5217 /*-----------------------------------------------------------------*/
5218 int OptimizepCode(char dbName)
5220 #define MAX_PASSES 4
5229 DFPRINTF((stderr," Optimizing pCode\n"));
5233 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5234 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5235 matches += OptimizepBlock(pb);
5238 while(matches && ++passes < MAX_PASSES);
5243 /*-----------------------------------------------------------------*/
5244 /* popCopyGPR2Bit - copy a pcode operator */
5245 /*-----------------------------------------------------------------*/
5247 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5251 pcop = newpCodeOpBit(pc->name, bitval, 0);
5253 if( !( (pcop->type == PO_LABEL) ||
5254 (pcop->type == PO_LITERAL) ||
5255 (pcop->type == PO_STR) ))
5256 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5262 /*-----------------------------------------------------------------*/
5263 /*-----------------------------------------------------------------*/
5264 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5267 int firstBank = 'U';
5272 for (pc=pb->pcHead; pc; pc=pc->next) {
5274 firstBank = PCFL(pc)->firstBank;
5278 if (firstBank != 'U') {
5279 /* This block has already been done */
5280 if (firstBank != cur_bank) {
5281 /* This block has started with a different bank - must adjust it */
5282 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5285 regs *reg = getRegFromInstruction(pc);
5287 DoBankSelect(pc,cur_bank);
5297 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5300 for (pc=pb->pcHead; pc; pc=pc->next) {
5302 PCFL(pc)->firstBank = cur_bank;
5305 cur_bank = DoBankSelect(pc,cur_bank);
5308 /* Trace through branches and set the bank selection as required. */
5311 for (pc=pb->pcHead; pc; pc=pc->next) {
5313 PCFL(pc)->firstBank = cur_bank;
5317 if (PCI(pc)->op == POC_GOTO) {
5318 int lastRegIdx = LastRegIdx;
5320 /* Trace through branch */
5321 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5324 regs *reg = getRegFromInstruction(pcl);
5326 int bankUnknown = -1;
5327 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5329 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5335 LastRegIdx = lastRegIdx;
5337 /* Keep track out current bank */
5338 regs *reg = getRegFromInstruction(pc);
5340 IsBankChange(pc,reg,&cur_bank);
5347 /*-----------------------------------------------------------------*/
5348 /*-----------------------------------------------------------------*/
5349 void pBlockDestruct(pBlock *pb)
5360 /*-----------------------------------------------------------------*/
5361 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5362 /* name dbName and combine them */
5363 /* into one block */
5364 /*-----------------------------------------------------------------*/
5365 void mergepBlocks(char dbName)
5368 pBlock *pb, *pbmerged = NULL,*pbn;
5370 pb = the_pFile->pbHead;
5372 //fprintf(stderr," merging blocks named %c\n",dbName);
5376 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5377 if( getpBlock_dbName(pb) == dbName) {
5379 //fprintf(stderr," merged block %c\n",dbName);
5384 addpCode2pBlock(pbmerged, pb->pcHead);
5385 /* addpCode2pBlock doesn't handle the tail: */
5386 pbmerged->pcTail = pb->pcTail;
5388 pb->prev->next = pbn;
5390 pbn->prev = pb->prev;
5395 //printpBlock(stderr, pbmerged);
5402 /*-----------------------------------------------------------------*/
5403 /* AnalyzeFlow - Examine the flow of the code and optimize */
5405 /* level 0 == minimal optimization */
5406 /* optimize registers that are used only by two instructions */
5407 /* level 1 == maximal optimization */
5408 /* optimize by looking at pairs of instructions that use the */
5410 /*-----------------------------------------------------------------*/
5412 void AnalyzeFlow(int level)
5414 static int times_called=0;
5422 /* if this is not the first time this function has been called,
5423 then clean up old flow information */
5424 if(times_called++) {
5425 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5428 RegsUnMapLiveRanges();
5434 /* Phase 2 - Flow Analysis - Register Banking
5436 * In this phase, the individual flow blocks are examined
5437 * and register banking is fixed.
5440 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5441 //FixRegisterBanking(pb);
5443 /* Phase 2 - Flow Analysis
5445 * In this phase, the pCode is partition into pCodeFlow
5446 * blocks. The flow blocks mark the points where a continuous
5447 * stream of instructions changes flow (e.g. because of
5448 * a call or goto or whatever).
5451 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5455 /* Phase 2 - Flow Analysis - linking flow blocks
5457 * In this phase, the individual flow blocks are examined
5458 * to determine their order of excution.
5461 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5464 /* Phase 3 - Flow Analysis - Flow Tree
5466 * In this phase, the individual flow blocks are examined
5467 * to determine their order of excution.
5470 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5474 /* Phase x - Flow Analysis - Used Banks
5476 * In this phase, the individual flow blocks are examined
5477 * to determine the Register Banks they use
5480 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5484 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5485 pCodeRegMapLiveRanges(pb);
5487 RemoveUnusedRegisters();
5489 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5490 pCodeRegOptimizeRegUsage(level);
5496 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5501 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5503 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5504 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5505 pcflow = pcflow->next) {
5507 FillFlow(PCFL(pcflow));
5512 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5514 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5515 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5516 pcflow = pcflow->next) {
5518 FlowStats(PCFL(pcflow));
5524 /*-----------------------------------------------------------------*/
5525 /* AnalyzeBanking - Called after the memory addresses have been */
5526 /* assigned to the registers. */
5528 /*-----------------------------------------------------------------*/
5530 void AnalyzeBanking(void)
5534 if(!picIsInitialized()) {
5535 setDefMaxRam(); // Max RAM has not been included, so use default setting
5538 /* Phase x - Flow Analysis - Used Banks
5540 * In this phase, the individual flow blocks are examined
5541 * to determine the Register Banks they use
5547 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5548 // BanksUsedFlow(pb);
5549 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5550 FixRegisterBanking(pb,-1); // cur_bank is unknown
5554 /*-----------------------------------------------------------------*/
5555 /*-----------------------------------------------------------------*/
5556 DEFSETFUNC (resetrIdx)
5558 regs *r = (regs *)item;
5566 /*-----------------------------------------------------------------*/
5567 /* InitRegReuse - Initialises variables for code analyzer */
5568 /*-----------------------------------------------------------------*/
5570 void InitReuseReg(void)
5572 /* Find end of statically allocated variables for start idx */
5573 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5575 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5576 if (r->type != REG_SFR) {
5577 maxIdx += r->size; /* Increment for all statically allocated variables */
5581 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5584 /*-----------------------------------------------------------------*/
5585 /*-----------------------------------------------------------------*/
5586 static unsigned register_reassign(pBlock *pb, unsigned idx)
5590 /* check recursion */
5591 pc = setFirstItem(pb->function_entries);
5597 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5599 if (pb->tregisters) {
5601 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5602 if (r->type == REG_GPR) {
5604 if (r->rIdx < (int)idx) {
5607 if (peakIdx < idx) peakIdx = idx;
5608 sprintf(s,"r0x%02X", r->rIdx);
5609 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5611 r->name = Safe_strdup(s);
5617 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5619 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5620 char *dest = get_op_from_instruction(PCI(pc));
5622 pCode *pcn = findFunction(dest);
5624 register_reassign(pcn->pb,idx);
5633 /*------------------------------------------------------------------*/
5634 /* ReuseReg were call tree permits */
5636 /* Re-allocate the GPR for optimum reuse for a given pblock */
5637 /* eg if a function m() calls function f1() and f2(), where f1 */
5638 /* allocates a local variable vf1 and f2 allocates a local */
5639 /* variable vf2. Then providing f1 and f2 do not call each other */
5640 /* they may share the same general purpose registers for vf1 and */
5642 /* This is done by first setting the the regs rIdx to start after */
5643 /* all the global variables, then walking through the call tree */
5644 /* renaming the registers to match their new idx and incrementng */
5645 /* it as it goes. If a function has already been called it will */
5646 /* only rename the registers if it has already used up those */
5647 /* registers ie rIdx of the function's registers is lower than the */
5648 /* current rIdx. That way the register will not be reused while */
5649 /* still being used by an eariler function call. */
5651 /* Note for this to work the functions need to be declared static. */
5653 /*------------------------------------------------------------------*/
5658 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5659 /* Non static functions can be called from other modules so their registers must reassign */
5660 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5661 register_reassign(pb,peakIdx);
5665 /*-----------------------------------------------------------------*/
5666 /* buildCallTree - look at the flow and extract all of the calls */
5668 /*-----------------------------------------------------------------*/
5670 void buildCallTree(void )
5679 /* Now build the call tree.
5680 First we examine all of the pCodes for functions.
5681 Keep in mind that the function boundaries coincide
5682 with pBlock boundaries.
5684 The algorithm goes something like this:
5685 We have two nested loops. The outer loop iterates
5686 through all of the pBlocks/functions. The inner
5687 loop iterates through all of the pCodes for
5688 a given pBlock. When we begin iterating through
5689 a pBlock, the variable pc_fstart, pCode of the start
5690 of a function, is cleared. We then search for pCodes
5691 of type PC_FUNCTION. When one is encountered, we
5692 initialize pc_fstart to this and at the same time
5693 associate a new pBranch object that signifies a
5694 branch entry. If a return is found, then this signifies
5695 a function exit point. We'll link the pCodes of these
5696 returns to the matching pc_fstart.
5698 When we're done, a doubly linked list of pBranches
5699 will exist. The head of this list is stored in
5700 `the_pFile', which is the meta structure for all
5701 of the pCode. Look at the printCallTree function
5702 on how the pBranches are linked together.
5705 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5706 pCode *pc_fstart=NULL;
5707 for(pc = pb->pcHead; pc; pc = pc->next) {
5709 pCodeFunction *pcf = PCF(pc);
5712 if(STRCASECMP(pcf->fname, "_main") == 0) {
5713 //fprintf(stderr," found main \n");
5714 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5718 pbr = Safe_calloc(1,sizeof(pBranch));
5719 pbr->pc = pc_fstart = pc;
5722 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5724 // Here's a better way of doing the same:
5725 addSet(&pb->function_entries, pc);
5728 // Found an exit point in a function, e.g. return
5729 // (Note, there may be more than one return per function)
5731 pBranchLink(PCF(pc_fstart), pcf);
5733 addSet(&pb->function_exits, pc);
5735 } else if(isCALL(pc)) {
5736 addSet(&pb->function_calls,pc);
5742 /*-----------------------------------------------------------------*/
5743 /* AnalyzepCode - parse the pCode that has been generated and form */
5744 /* all of the logical connections. */
5746 /* Essentially what's done here is that the pCode flow is */
5748 /*-----------------------------------------------------------------*/
5750 void AnalyzepCode(char dbName)
5761 /* Phase 1 - Register allocation and peep hole optimization
5763 * The first part of the analysis is to determine the registers
5764 * that are used in the pCode. Once that is done, the peep rules
5765 * are applied to the code. We continue to loop until no more
5766 * peep rule optimizations are found (or until we exceed the
5767 * MAX_PASSES threshold).
5769 * When done, the required registers will be determined.
5775 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5777 /* First, merge the labels with the instructions */
5778 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5779 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5781 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5782 pBlockMergeLabels(pb);
5785 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5789 changes = OptimizepCode(dbName);
5791 } while(changes && (i++ < MAX_PASSES));
5796 /*-----------------------------------------------------------------*/
5797 /* ispCodeFunction - returns true if *pc is the pCode of a */
5799 /*-----------------------------------------------------------------*/
5800 bool ispCodeFunction(pCode *pc)
5803 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5809 /*-----------------------------------------------------------------*/
5810 /* findFunction - Search for a function by name (given the name) */
5811 /* in the set of all functions that are in a pBlock */
5812 /* (note - I expect this to change because I'm planning to limit */
5813 /* pBlock's to just one function declaration */
5814 /*-----------------------------------------------------------------*/
5815 pCode *findFunction(char *fname)
5822 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5824 pc = setFirstItem(pb->function_entries);
5827 if((pc->type == PC_FUNCTION) &&
5829 (strcmp(fname, PCF(pc)->fname)==0))
5832 pc = setNextItem(pb->function_entries);
5840 void MarkUsedRegisters(set *regset)
5845 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5846 r2 = pic14_regWithIdx(r1->rIdx);
5854 void pBlockStats(FILE *of, pBlock *pb)
5860 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5862 // for now just print the first element of each set
5863 pc = setFirstItem(pb->function_entries);
5865 fprintf(of,";entry: ");
5868 pc = setFirstItem(pb->function_exits);
5870 fprintf(of,";has an exit\n");
5874 pc = setFirstItem(pb->function_calls);
5876 fprintf(of,";functions called:\n");
5879 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5880 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5882 pc = setNextItem(pb->function_calls);
5886 r = setFirstItem(pb->tregisters);
5888 int n = elementsInSet(pb->tregisters);
5890 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5893 fprintf(of,"; %s\n",r->name);
5894 r = setNextItem(pb->tregisters);
5899 /*-----------------------------------------------------------------*/
5900 /*-----------------------------------------------------------------*/
5902 static void sequencepCode(void)
5908 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5910 pb->seq = GpCodeSequenceNumber+1;
5912 for( pc = pb->pcHead; pc; pc = pc->next)
5913 pc->seq = ++GpCodeSequenceNumber;
5919 /*-----------------------------------------------------------------*/
5920 /*-----------------------------------------------------------------*/
5922 set *register_usage(pBlock *pb)
5925 set *registers=NULL;
5926 set *registersInCallPath = NULL;
5928 / * check recursion * /
5930 pc = setFirstItem(pb->function_entries);
5937 if(pc->type != PC_FUNCTION)
5938 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5940 pc = setFirstItem(pb->function_calls);
5941 for( ; pc; pc = setNextItem(pb->function_calls)) {
5943 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5944 char *dest = get_op_from_instruction(PCI(pc));
5946 pcn = findFunction(dest);
5948 registersInCallPath = register_usage(pcn->pb);
5950 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5955 pBlockStats(stderr,pb); // debug
5958 // Mark the registers in this block as used.
5960 MarkUsedRegisters(pb->tregisters);
5961 if(registersInCallPath) {
5962 / * registers were used in the functions this pBlock has called * /
5963 / * so now, we need to see if these collide with the ones we are * /
5966 regs *r1,*r2, *newreg;
5968 DFPRINTF((stderr,"comparing registers\n"));
5970 r1 = setFirstItem(registersInCallPath);
5972 if (r1->type != REG_STK) {
5973 r2 = setFirstItem(pb->tregisters);
5975 while(r2 && (r2->type != REG_STK)) {
5977 if(r2->rIdx == r1->rIdx) {
5978 newreg = pic14_findFreeReg(REG_GPR);
5982 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5986 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5987 r1->rIdx, newreg->rIdx));
5988 r2->rIdx = newreg->rIdx;
5990 r2->name = Safe_strdup(newreg->name);
5994 newreg->wasUsed = 1;
5996 r2 = setNextItem(pb->tregisters);
6000 r1 = setNextItem(registersInCallPath);
6003 / * Collisions have been resolved. Now free the registers in the call path * /
6004 r1 = setFirstItem(registersInCallPath);
6006 newreg = pic14_regWithIdx(r1->rIdx);
6007 if (newreg) newreg->isFree = 1;
6008 r1 = setNextItem(registersInCallPath);
6012 // MarkUsedRegisters(pb->registers);
6014 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6017 DFPRINTF((stderr,"returning regs\n"));
6019 DFPRINTF((stderr,"not returning regs\n"));
6021 DFPRINTF((stderr,"pBlock after register optim.\n"));
6022 pBlockStats(stderr,pb); // debug
6029 /*-----------------------------------------------------------------*/
6030 /* printCallTree - writes the call tree to a file */
6032 /*-----------------------------------------------------------------*/
6033 void pct2(FILE *of,pBlock *pb,int indent)
6037 // set *registersInCallPath = NULL;
6043 return; //recursion ?
6045 pc = setFirstItem(pb->function_entries);
6052 for(i=0;i<indent;i++) // Indentation
6055 if(pc->type == PC_FUNCTION)
6056 fprintf(of,"%s\n",PCF(pc)->fname);
6061 pc = setFirstItem(pb->function_calls);
6062 for( ; pc; pc = setNextItem(pb->function_calls)) {
6064 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6065 char *dest = get_op_from_instruction(PCI(pc));
6067 pcn = findFunction(dest);
6069 pct2(of,pcn->pb,indent+1);
6071 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6079 /*-----------------------------------------------------------------*/
6080 /* printCallTree - writes the call tree to a file */
6082 /*-----------------------------------------------------------------*/
6084 void printCallTree(FILE *of)
6096 fprintf(of, "\npBlock statistics\n");
6097 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6102 fprintf(of,"Call Tree\n");
6103 pbr = the_pFile->functions;
6107 if(!ispCodeFunction(pc))
6108 fprintf(of,"bug in call tree");
6111 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6113 while(pc->next && !ispCodeFunction(pc->next)) {
6115 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6116 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6124 fprintf(of,"\n**************\n\na better call tree\n");
6125 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6130 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6131 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6137 /*-----------------------------------------------------------------*/
6139 /*-----------------------------------------------------------------*/
6141 void InlineFunction(pBlock *pb)
6149 pc = setFirstItem(pb->function_calls);
6151 for( ; pc; pc = setNextItem(pb->function_calls)) {
6154 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6155 pCode *pcp = pc->prev;
6161 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 */
6163 InlineFunction(pcn->pb);
6166 At this point, *pc points to a CALL mnemonic, and
6167 *pcn points to the function that is being called.
6169 To in-line this call, we need to remove the CALL
6170 and RETURN(s), and link the function pCode in with
6177 /* Check if previous instruction was a bit skip */
6178 if (isPCI_BITSKIP(pcp)) {
6180 /* Invert skip instruction and add a goto */
6181 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6183 if(isPCL(pc_call->next)) { // Label pcode
6184 pcl = PCL(pc_call->next);
6185 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6186 pcl = PCL(PCI(pc_call->next)->label->pc);
6188 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6189 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6191 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6194 /* remove callee pBlock from the pBlock linked list */
6195 removepBlock(pcn->pb);
6203 /* Remove the Function pCode */
6204 pct = findNextInstruction(pcn->next);
6206 /* Link the function with the callee */
6207 if (pcp) pcp->next = pcn->next;
6208 pcn->next->prev = pcp;
6210 /* Convert the function name into a label */
6212 pbr = Safe_calloc(1,sizeof(pBranch));
6213 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6215 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6216 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6218 /* turn all of the return's except the last into goto's */
6219 /* check case for 2 instruction pBlocks */
6220 pce = findNextInstruction(pcn->next);
6222 pCode *pce_next = findNextInstruction(pce->next);
6224 if(pce_next == NULL) {
6225 /* found the last return */
6226 pCode *pc_call_next = findNextInstruction(pc_call->next);
6228 //fprintf(stderr,"found last return\n");
6229 //pce->print(stderr,pce);
6230 pce->prev->next = pc_call->next;
6231 pc_call->next->prev = pce->prev;
6232 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6241 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6247 /*-----------------------------------------------------------------*/
6249 /*-----------------------------------------------------------------*/
6251 void InlinepCode(void)
6260 if(!functionInlining)
6263 /* Loop through all of the function definitions and count the
6264 * number of times each one is called */
6265 //fprintf(stderr,"inlining %d\n",__LINE__);
6267 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6269 pc = setFirstItem(pb->function_calls);
6271 for( ; pc; pc = setNextItem(pb->function_calls)) {
6274 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6275 if(pcn && isPCF(pcn)) {
6276 PCF(pcn)->ncalled++;
6279 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6284 //fprintf(stderr,"inlining %d\n",__LINE__);
6286 /* Now, Loop through the function definitions again, but this
6287 * time inline those functions that have only been called once. */
6289 InlineFunction(the_pFile->pbHead);
6290 //fprintf(stderr,"inlining %d\n",__LINE__);
6292 for(pb = the_pFile->pbHead; pb; pb = pb->next)