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);
127 pBranch * pBranchAppend(pBranch *h, pBranch *n);
130 /****************************************************************/
131 /* PIC Instructions */
132 /****************************************************************/
134 pCodeInstruction pciADDWF = {
135 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
148 1,0, // dest, bit instruction
150 0, // literal operand
152 (PCC_W | PCC_REGISTER), // inCond
153 (PCC_REGISTER | PCC_Z) // outCond
156 pCodeInstruction pciADDFW = {
157 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
170 0,0, // dest, bit instruction
172 0, // literal operand
174 (PCC_W | PCC_REGISTER), // inCond
175 (PCC_W | PCC_Z) // outCond
178 pCodeInstruction pciADDLW = {
179 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
192 0,0, // dest, bit instruction
194 1, // literal operand
196 (PCC_W | PCC_LITERAL), // inCond
197 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
200 pCodeInstruction pciANDLW = {
201 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
214 0,0, // dest, bit instruction
216 1, // literal operand
218 (PCC_W | PCC_LITERAL), // inCond
219 (PCC_W | PCC_Z) // outCond
222 pCodeInstruction pciANDWF = {
223 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
236 1,0, // dest, bit instruction
238 0, // literal operand
240 (PCC_W | PCC_REGISTER), // inCond
241 (PCC_REGISTER | PCC_Z) // outCond
244 pCodeInstruction pciANDFW = {
245 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
258 0,0, // dest, bit instruction
260 0, // literal operand
262 (PCC_W | PCC_REGISTER), // inCond
263 (PCC_W | PCC_Z) // outCond
266 pCodeInstruction pciBCF = {
267 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
280 1,1, // dest, bit instruction
282 0, // literal operand
284 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
285 PCC_REGISTER // outCond
288 pCodeInstruction pciBSF = {
289 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
302 1,1, // dest, bit instruction
304 0, // literal operand
306 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
307 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
310 pCodeInstruction pciBTFSC = {
311 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
324 0,1, // dest, bit instruction
326 0, // literal operand
328 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
329 PCC_EXAMINE_PCOP // outCond
332 pCodeInstruction pciBTFSS = {
333 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
346 0,1, // dest, bit instruction
348 0, // literal operand
350 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
351 PCC_EXAMINE_PCOP // outCond
354 pCodeInstruction pciCALL = {
355 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
368 0,0, // dest, bit instruction
370 0, // literal operand
376 pCodeInstruction pciCOMF = {
377 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
390 1,0, // dest, bit instruction
392 0, // literal operand
394 PCC_REGISTER, // inCond
395 PCC_REGISTER // outCond
398 pCodeInstruction pciCOMFW = {
399 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
412 0,0, // dest, bit instruction
414 0, // literal operand
416 PCC_REGISTER, // inCond
420 pCodeInstruction pciCLRF = {
421 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
434 0,0, // dest, bit instruction
436 0, // literal operand
439 PCC_REGISTER // outCond
442 pCodeInstruction pciCLRW = {
443 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
456 0,0, // dest, bit instruction
458 0, // literal operand
464 pCodeInstruction pciCLRWDT = {
465 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
478 0,0, // dest, bit instruction
480 0, // literal operand
486 pCodeInstruction pciDECF = {
487 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
500 1,0, // dest, bit instruction
502 0, // literal operand
504 PCC_REGISTER, // inCond
505 PCC_REGISTER // outCond
508 pCodeInstruction pciDECFW = {
509 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
522 0,0, // dest, bit instruction
524 0, // literal operand
526 PCC_REGISTER, // inCond
530 pCodeInstruction pciDECFSZ = {
531 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
544 1,0, // dest, bit instruction
546 0, // literal operand
548 PCC_REGISTER, // inCond
549 PCC_REGISTER // outCond
552 pCodeInstruction pciDECFSZW = {
553 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
566 0,0, // dest, bit instruction
568 0, // literal operand
570 PCC_REGISTER, // inCond
574 pCodeInstruction pciGOTO = {
575 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
588 0,0, // dest, bit instruction
590 0, // literal operand
596 pCodeInstruction pciINCF = {
597 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
610 1,0, // dest, bit instruction
612 0, // literal operand
614 PCC_REGISTER, // inCond
615 PCC_REGISTER // outCond
618 pCodeInstruction pciINCFW = {
619 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
632 0,0, // dest, bit instruction
634 0, // literal operand
636 PCC_REGISTER, // inCond
640 pCodeInstruction pciINCFSZ = {
641 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
654 1,0, // dest, bit instruction
656 0, // literal operand
658 PCC_REGISTER, // inCond
659 PCC_REGISTER // outCond
662 pCodeInstruction pciINCFSZW = {
663 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
676 0,0, // dest, bit instruction
678 0, // literal operand
680 PCC_REGISTER, // inCond
684 pCodeInstruction pciIORWF = {
685 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
698 1,0, // dest, bit instruction
700 0, // literal operand
702 (PCC_W | PCC_REGISTER), // inCond
703 (PCC_REGISTER | PCC_Z) // outCond
706 pCodeInstruction pciIORFW = {
707 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
720 0,0, // dest, bit instruction
722 0, // literal operand
724 (PCC_W | PCC_REGISTER), // inCond
725 (PCC_W | PCC_Z) // outCond
728 pCodeInstruction pciIORLW = {
729 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
742 0,0, // dest, bit instruction
744 1, // literal operand
746 (PCC_W | PCC_LITERAL), // inCond
747 (PCC_W | PCC_Z) // outCond
750 pCodeInstruction pciMOVF = {
751 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
764 1,0, // dest, bit instruction
766 0, // literal operand
768 PCC_REGISTER, // inCond
772 pCodeInstruction pciMOVFW = {
773 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
786 0,0, // dest, bit instruction
788 0, // literal operand
790 PCC_REGISTER, // inCond
791 (PCC_W | PCC_Z) // outCond
794 pCodeInstruction pciMOVWF = {
795 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
808 0,0, // dest, bit instruction
810 0, // literal operand
813 PCC_REGISTER // outCond
816 pCodeInstruction pciMOVLW = {
817 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
829 0,0, // dest, bit instruction
831 1, // literal operand
833 (PCC_NONE | PCC_LITERAL), // inCond
837 pCodeInstruction pciNOP = {
838 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
850 0,0, // dest, bit instruction
852 0, // literal operand
858 pCodeInstruction pciRETFIE = {
859 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
872 0,0, // dest, bit instruction
874 0, // literal operand
877 PCC_NONE // outCond (not true... affects the GIE bit too)
880 pCodeInstruction pciRETLW = {
881 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
894 0,0, // dest, bit instruction
896 1, // literal operand
898 PCC_LITERAL, // inCond
902 pCodeInstruction pciRETURN = {
903 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
916 0,0, // dest, bit instruction
918 0, // literal operand
924 pCodeInstruction pciRLF = {
925 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
938 1,0, // dest, bit instruction
940 0, // literal operand
942 (PCC_C | PCC_REGISTER), // inCond
943 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
946 pCodeInstruction pciRLFW = {
947 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
960 0,0, // dest, bit instruction
962 0, // literal operand
964 (PCC_C | PCC_REGISTER), // inCond
965 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
968 pCodeInstruction pciRRF = {
969 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
982 1,0, // dest, bit instruction
984 0, // literal operand
986 (PCC_C | PCC_REGISTER), // inCond
987 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
990 pCodeInstruction pciRRFW = {
991 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1004 0,0, // dest, bit instruction
1005 0,0, // branch, skip
1006 0, // literal operand
1008 (PCC_C | PCC_REGISTER), // inCond
1009 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1012 pCodeInstruction pciSUBWF = {
1013 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1019 NULL, // from branch
1026 1,0, // dest, bit instruction
1027 0,0, // branch, skip
1028 0, // literal operand
1030 (PCC_W | PCC_REGISTER), // inCond
1031 (PCC_REGISTER | PCC_Z) // outCond
1034 pCodeInstruction pciSUBFW = {
1035 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1041 NULL, // from branch
1048 0,0, // dest, bit instruction
1049 0,0, // branch, skip
1050 0, // literal operand
1052 (PCC_W | PCC_REGISTER), // inCond
1053 (PCC_W | PCC_Z) // outCond
1056 pCodeInstruction pciSUBLW = {
1057 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1063 NULL, // from branch
1070 0,0, // dest, bit instruction
1071 0,0, // branch, skip
1072 1, // literal operand
1074 (PCC_W | PCC_LITERAL), // inCond
1075 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1078 pCodeInstruction pciSWAPF = {
1079 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1085 NULL, // from branch
1092 1,0, // dest, bit instruction
1093 0,0, // branch, skip
1094 0, // literal operand
1096 (PCC_REGISTER), // inCond
1097 (PCC_REGISTER) // outCond
1100 pCodeInstruction pciSWAPFW = {
1101 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1107 NULL, // from branch
1114 0,0, // dest, bit instruction
1115 0,0, // branch, skip
1116 0, // literal operand
1118 (PCC_REGISTER), // inCond
1122 pCodeInstruction pciTRIS = {
1123 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1129 NULL, // from branch
1136 0,0, // dest, bit instruction
1137 0,0, // branch, skip
1138 0, // literal operand
1141 PCC_REGISTER // outCond
1144 pCodeInstruction pciXORWF = {
1145 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1151 NULL, // from branch
1158 1,0, // dest, bit instruction
1159 0,0, // branch, skip
1160 0, // literal operand
1162 (PCC_W | PCC_REGISTER), // inCond
1163 (PCC_REGISTER | PCC_Z) // outCond
1166 pCodeInstruction pciXORFW = {
1167 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1173 NULL, // from branch
1180 0,0, // dest, bit instruction
1181 0,0, // branch, skip
1182 0, // literal operand
1184 (PCC_W | PCC_REGISTER), // inCond
1185 (PCC_W | PCC_Z) // outCond
1188 pCodeInstruction pciXORLW = {
1189 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1195 NULL, // from branch
1202 0,0, // dest, bit instruction
1203 0,0, // branch, skip
1204 1, // literal operand
1206 (PCC_W | PCC_LITERAL), // inCond
1207 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1211 pCodeInstruction pciBANKSEL = {
1212 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1218 NULL, // from branch
1225 0,0, // dest, bit instruction
1226 0,0, // branch, skip
1227 0, // literal operand
1230 PCC_REGISTER // outCond
1233 pCodeInstruction pciPAGESEL = {
1234 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1240 NULL, // from branch
1247 0,0, // dest, bit instruction
1248 0,0, // branch, skip
1249 0, // literal operand
1252 PCC_REGISTER // outCond
1255 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1258 /*-----------------------------------------------------------------*/
1259 /* return a unique ID number to assist pCodes debuging */
1260 /*-----------------------------------------------------------------*/
1261 unsigned PCodeID(void) {
1262 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1264 static unsigned int stop;
1265 if (pcodeId == 1448)
1266 stop++; // Place break point here
1271 #ifdef HAVE_VSNPRINTF
1272 // Alas, vsnprintf is not ANSI standard, and does not exist
1273 // on Solaris (and probably other non-Gnu flavored Unixes).
1275 /*-----------------------------------------------------------------*/
1276 /* SAFE_snprintf - like snprintf except the string pointer is */
1277 /* after the string has been printed to. This is */
1278 /* useful for printing to string as though if it */
1279 /* were a stream. */
1280 /*-----------------------------------------------------------------*/
1281 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1289 va_start(val, format);
1291 vsnprintf(*str, *size, format, val);
1296 if((size_t)len > *size) {
1297 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1298 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1306 #else // HAVE_VSNPRINTF
1308 // This version is *not* safe, despite the name.
1310 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1314 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1319 va_start(val, format);
1321 vsprintf(buffer, format, val);
1324 len = strlen(buffer);
1326 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1327 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1330 strcpy(*str, buffer);
1336 #endif // HAVE_VSNPRINTF
1339 extern void initStack(int base_address, int size);
1340 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1341 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1342 extern void init_pic(char *);
1344 void pCodeInitRegisters(void)
1346 static int initialized=0;
1347 int shareBankAddress,stkSize;
1353 init_pic(port->processor);
1354 shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1355 if ((unsigned)shareBankAddress > getMaxRam()) /* If total RAM is less than 0x7f as with 16f84 then reduce shareBankAddress to fit */
1356 shareBankAddress = (int)getMaxRam();
1357 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 */
1358 initStack(shareBankAddress, stkSize); /* Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters */
1360 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1361 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1362 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1363 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1364 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1365 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1367 pc_status.rIdx = IDX_STATUS;
1368 pc_fsr.rIdx = IDX_FSR;
1369 pc_indf.rIdx = IDX_INDF;
1370 pc_intcon.rIdx = IDX_INTCON;
1371 pc_pcl.rIdx = IDX_PCL;
1372 pc_pclath.rIdx = IDX_PCLATH;
1374 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. */
1375 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, 0); /* Interrupt storage for status register. */
1376 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, 0); /* Interrupt storage for pclath register. */
1378 pc_wsave.rIdx = pc_wsave.r->rIdx;
1379 pc_ssave.rIdx = pc_ssave.r->rIdx;
1380 pc_psave.rIdx = pc_psave.r->rIdx;
1382 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1383 pc_wsave.r->address = shareBankAddress-stkSize;
1384 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1385 pc_ssave.r->address = shareBankAddress-stkSize-1;
1386 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1387 pc_psave.r->address = shareBankAddress-stkSize-2;
1389 /* probably should put this in a separate initialization routine */
1390 pb_dead_pcodes = newpBlock();
1394 /*-----------------------------------------------------------------*/
1395 /* mnem2key - convert a pic mnemonic into a hash key */
1396 /* (BTW - this spreads the mnemonics quite well) */
1398 /*-----------------------------------------------------------------*/
1400 int mnem2key(unsigned char const *mnem)
1409 key += toupper(*mnem++) +1;
1413 return (key & 0x1f);
1417 void pic14initMnemonics(void)
1422 pCodeInstruction *pci;
1424 if(mnemonics_initialized)
1427 //FIXME - probably should NULL out the array before making the assignments
1428 //since we check the array contents below this initialization.
1430 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1431 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1432 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1433 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1434 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1435 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1436 pic14Mnemonics[POC_BCF] = &pciBCF;
1437 pic14Mnemonics[POC_BSF] = &pciBSF;
1438 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1439 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1440 pic14Mnemonics[POC_CALL] = &pciCALL;
1441 pic14Mnemonics[POC_COMF] = &pciCOMF;
1442 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1443 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1444 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1445 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1446 pic14Mnemonics[POC_DECF] = &pciDECF;
1447 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1448 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1449 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1450 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1451 pic14Mnemonics[POC_INCF] = &pciINCF;
1452 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1453 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1454 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1455 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1456 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1457 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1458 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1459 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1460 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1461 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1462 pic14Mnemonics[POC_NOP] = &pciNOP;
1463 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1464 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1465 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1466 pic14Mnemonics[POC_RLF] = &pciRLF;
1467 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1468 pic14Mnemonics[POC_RRF] = &pciRRF;
1469 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1470 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1471 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1472 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1473 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1474 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1475 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1476 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1477 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1478 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1479 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1480 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1482 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1483 if(pic14Mnemonics[i])
1484 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1485 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1488 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1489 pci = hTabNextItem(pic14MnemonicsHash, &key);
1492 mnemonics_initialized = 1;
1495 int getpCodePeepCommand(char *cmd);
1497 int getpCode(char *mnem,unsigned dest)
1500 pCodeInstruction *pci;
1501 int key = mnem2key(mnem);
1503 if(!mnemonics_initialized)
1504 pic14initMnemonics();
1506 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1510 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1511 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1515 pci = hTabNextItemWK (pic14MnemonicsHash);
1522 /*-----------------------------------------------------------------*
1523 * pic14initpCodePeepCommands
1525 *-----------------------------------------------------------------*/
1526 void pic14initpCodePeepCommands(void)
1534 hTabAddItem(&pic14pCodePeepCommandsHash,
1535 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1537 } while (peepCommands[i].cmd);
1539 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1542 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1543 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1548 /*-----------------------------------------------------------------
1551 *-----------------------------------------------------------------*/
1553 int getpCodePeepCommand(char *cmd)
1557 int key = mnem2key(cmd);
1560 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1563 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1564 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1568 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1575 char getpBlock_dbName(pBlock *pb)
1581 return pb->cmemmap->dbName;
1585 void pBlockConvert2ISR(pBlock *pb)
1596 /*-----------------------------------------------------------------*/
1597 /* movepBlock2Head - given the dbname of a pBlock, move all */
1598 /* instances to the front of the doubly linked */
1599 /* list of pBlocks */
1600 /*-----------------------------------------------------------------*/
1602 void movepBlock2Head(char dbName)
1609 pb = the_pFile->pbHead;
1613 if(getpBlock_dbName(pb) == dbName) {
1614 pBlock *pbn = pb->next;
1615 pb->next = the_pFile->pbHead;
1616 the_pFile->pbHead->prev = pb;
1617 the_pFile->pbHead = pb;
1620 pb->prev->next = pbn;
1622 // If the pBlock that we just moved was the last
1623 // one in the link of all of the pBlocks, then we
1624 // need to point the tail to the block just before
1625 // the one we moved.
1626 // Note: if pb->next is NULL, then pb must have
1627 // been the last pBlock in the chain.
1630 pbn->prev = pb->prev;
1632 the_pFile->pbTail = pb->prev;
1643 void copypCode(FILE *of, char dbName)
1647 if(!of || !the_pFile)
1650 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1651 if(getpBlock_dbName(pb) == dbName) {
1660 void resetpCodeStatistics (void)
1662 pcode_insns = pcode_doubles = 0;
1665 void dumppCodeStatistics (FILE *of)
1667 /* dump statistics */
1669 fprintf (of, ";\tcode size estimation:\n");
1670 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1674 void pcode_test(void)
1677 DFPRINTF((stderr,"pcode is alive!\n"));
1687 /* create the file name */
1688 strcpy(buffer,dstFileName);
1689 strcat(buffer,".p");
1691 if( !(pFile = fopen(buffer, "w" ))) {
1692 werror(E_FILE_OPEN_ERR,buffer);
1696 fprintf(pFile,"pcode dump\n\n");
1698 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1699 fprintf(pFile,"\n\tNew pBlock\n\n");
1701 fprintf(pFile,"%s",pb->cmemmap->sname);
1703 fprintf(pFile,"internal pblock");
1705 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1706 printpBlock(pFile,pb);
1710 /*-----------------------------------------------------------------*/
1711 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1712 /* ister, RegCond will return the bit being referenced. */
1714 /* fixme - why not just OR in the pcop bit field */
1715 /*-----------------------------------------------------------------*/
1717 static int RegCond(pCodeOp *pcop)
1723 if (pcop->type == PO_GPR_BIT) {
1724 char *name = pcop->name;
1726 name = PCOR(pcop)->r->name;
1727 // if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1728 switch(PCORB(pcop)->bit) {
1742 /*-----------------------------------------------------------------*/
1743 /* newpCode - create and return a newly initialized pCode */
1745 /* fixme - rename this */
1747 /* The purpose of this routine is to create a new Instruction */
1748 /* pCode. This is called by gen.c while the assembly code is being */
1752 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1753 /* (note that the op is analogous to but not the */
1754 /* same thing as the opcode of the instruction.) */
1755 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1758 /* a pointer to the new malloc'd pCode is returned. */
1762 /*-----------------------------------------------------------------*/
1763 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1765 pCodeInstruction *pci ;
1767 if(!mnemonics_initialized)
1768 pic14initMnemonics();
1770 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1772 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1773 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1774 pci->pc.id = PCodeID();
1777 if(pci->inCond & PCC_EXAMINE_PCOP)
1778 pci->inCond |= RegCond(pcop);
1780 if(pci->outCond & PCC_EXAMINE_PCOP)
1781 pci->outCond |= RegCond(pcop);
1783 pci->pc.prev = pci->pc.next = NULL;
1784 return (pCode *)pci;
1787 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1793 /*-----------------------------------------------------------------*/
1794 /* newpCodeWild - create a "wild" as in wild card pCode */
1796 /* Wild pcodes are used during the peep hole optimizer to serve */
1797 /* as place holders for any instruction. When a snippet of code is */
1798 /* compared to a peep hole rule, the wild card opcode will match */
1799 /* any instruction. However, the optional operand and label are */
1800 /* additional qualifiers that must also be matched before the */
1801 /* line (of assembly code) is declared matched. Note that the */
1802 /* operand may be wild too. */
1804 /* Note, a wild instruction is specified just like a wild var: */
1805 /* %4 ; A wild instruction, */
1806 /* See the peeph.def file for additional examples */
1808 /*-----------------------------------------------------------------*/
1810 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1815 pcw = Safe_calloc(1,sizeof(pCodeWild));
1817 pcw->pci.pc.type = PC_WILD;
1818 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1819 pcw->id = PCodeID();
1820 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1821 pcw->pci.pc.pb = NULL;
1823 // pcw->pci.pc.analyze = genericAnalyze;
1824 pcw->pci.pc.destruct = genericDestruct;
1825 pcw->pci.pc.print = genericPrint;
1827 pcw->id = pCodeID; // this is the 'n' in %n
1828 pcw->operand = optional_operand;
1829 pcw->label = optional_label;
1831 pcw->mustBeBitSkipInst = 0;
1832 pcw->mustNotBeBitSkipInst = 0;
1833 pcw->invertBitSkipInst = 0;
1835 return ( (pCode *)pcw);
1839 /*-----------------------------------------------------------------*/
1840 /* newPcodeInlineP - create a new pCode from a char string */
1841 /*-----------------------------------------------------------------*/
1844 pCode *newpCodeInlineP(char *cP)
1849 pcc = Safe_calloc(1,sizeof(pCodeComment));
1851 pcc->pc.type = PC_INLINE;
1852 pcc->pc.prev = pcc->pc.next = NULL;
1853 pcc->pc.id = PCodeID();
1854 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1857 // pcc->pc.analyze = genericAnalyze;
1858 pcc->pc.destruct = genericDestruct;
1859 pcc->pc.print = genericPrint;
1862 pcc->comment = Safe_strdup(cP);
1864 pcc->comment = NULL;
1866 return ( (pCode *)pcc);
1870 /*-----------------------------------------------------------------*/
1871 /* newPcodeCharP - create a new pCode from a char string */
1872 /*-----------------------------------------------------------------*/
1874 pCode *newpCodeCharP(char *cP)
1879 pcc = Safe_calloc(1,sizeof(pCodeComment));
1881 pcc->pc.type = PC_COMMENT;
1882 pcc->pc.prev = pcc->pc.next = NULL;
1883 pcc->pc.id = PCodeID();
1884 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1887 // pcc->pc.analyze = genericAnalyze;
1888 pcc->pc.destruct = genericDestruct;
1889 pcc->pc.print = genericPrint;
1892 pcc->comment = Safe_strdup(cP);
1894 pcc->comment = NULL;
1896 return ( (pCode *)pcc);
1900 /*-----------------------------------------------------------------*/
1901 /* newpCodeFunction - */
1902 /*-----------------------------------------------------------------*/
1905 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1909 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1910 //_ALLOC(pcf,sizeof(pCodeFunction));
1912 pcf->pc.type = PC_FUNCTION;
1913 pcf->pc.prev = pcf->pc.next = NULL;
1914 pcf->pc.id = PCodeID();
1915 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1918 // pcf->pc.analyze = genericAnalyze;
1919 pcf->pc.destruct = genericDestruct;
1920 pcf->pc.print = pCodePrintFunction;
1925 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1926 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1927 strcpy(pcf->modname,mod);
1929 pcf->modname = NULL;
1932 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1933 pcf->fname = Safe_calloc(1,strlen(f)+1);
1934 strcpy(pcf->fname,f);
1938 pcf->isPublic = (unsigned)isPublic;
1940 return ( (pCode *)pcf);
1944 /*-----------------------------------------------------------------*/
1946 /*-----------------------------------------------------------------*/
1947 void destructpCodeFlow(pCode *pc)
1949 if(!pc || !isPCFL(pc))
1958 deleteSet(&PCFL(pc)->registers);
1959 deleteSet(&PCFL(pc)->from);
1960 deleteSet(&PCFL(pc)->to);
1965 pCode *newpCodeFlow(void )
1969 //_ALLOC(pcflow,sizeof(pCodeFlow));
1970 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1972 pcflow->pc.type = PC_FLOW;
1973 pcflow->pc.prev = pcflow->pc.next = NULL;
1974 pcflow->pc.pb = NULL;
1976 // pcflow->pc.analyze = genericAnalyze;
1977 pcflow->pc.destruct = destructpCodeFlow;
1978 pcflow->pc.print = genericPrint;
1980 pcflow->pc.seq = GpcFlowSeq++;
1982 pcflow->from = pcflow->to = NULL;
1984 pcflow->inCond = PCC_NONE;
1985 pcflow->outCond = PCC_NONE;
1987 pcflow->firstBank = 'U'; /* Undetermined */
1988 pcflow->lastBank = 'U'; /* Undetermined */
1990 pcflow->FromConflicts = 0;
1991 pcflow->ToConflicts = 0;
1995 pcflow->registers = newSet();
1997 return ( (pCode *)pcflow);
2001 /*-----------------------------------------------------------------*/
2002 /*-----------------------------------------------------------------*/
2003 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2005 pCodeFlowLink *pcflowLink;
2007 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2009 pcflowLink->pcflow = pcflow;
2010 pcflowLink->bank_conflict = 0;
2015 /*-----------------------------------------------------------------*/
2016 /* newpCodeCSource - create a new pCode Source Symbol */
2017 /*-----------------------------------------------------------------*/
2019 pCode *newpCodeCSource(int ln, char *f, const char *l)
2024 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2026 pccs->pc.type = PC_CSOURCE;
2027 pccs->pc.prev = pccs->pc.next = NULL;
2028 pccs->pc.id = PCodeID();
2031 pccs->pc.destruct = genericDestruct;
2032 pccs->pc.print = genericPrint;
2034 pccs->line_number = ln;
2036 pccs->line = Safe_strdup(l);
2041 pccs->file_name = Safe_strdup(f);
2043 pccs->file_name = NULL;
2045 return ( (pCode *)pccs);
2049 /*******************************************************************/
2050 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2051 /* added by VR 6-Jun-2003 */
2052 /*******************************************************************/
2054 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2061 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2062 pcad->pci.pc.type = PC_ASMDIR;
2063 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2064 pcad->pci.pc.pb = NULL;
2065 pcad->pci.pc.destruct = genericDestruct;
2066 pcad->pci.pc.print = genericPrint;
2068 if(asdir && *asdir) {
2070 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2072 pcad->directive = Safe_strdup( asdir );
2075 va_start(ap, argfmt);
2077 memset(buffer, 0, sizeof(buffer));
2078 if(argfmt && *argfmt)
2079 vsprintf(buffer, argfmt, ap);
2083 while(isspace((unsigned char)*lbp))lbp++;
2086 pcad->arg = Safe_strdup( lbp );
2088 return ((pCode *)pcad);
2091 /*-----------------------------------------------------------------*/
2092 /* pCodeLabelDestruct - free memory used by a label. */
2093 /*-----------------------------------------------------------------*/
2094 static void pCodeLabelDestruct(pCode *pc)
2100 if((pc->type == PC_LABEL) && PCL(pc)->label)
2101 free(PCL(pc)->label);
2107 pCode *newpCodeLabel(char *name, int key)
2113 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2115 pcl->pc.type = PC_LABEL;
2116 pcl->pc.prev = pcl->pc.next = NULL;
2117 pcl->pc.id = PCodeID();
2118 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2121 // pcl->pc.analyze = genericAnalyze;
2122 pcl->pc.destruct = pCodeLabelDestruct;
2123 pcl->pc.print = pCodePrintLabel;
2129 sprintf(s,"_%05d_DS_",key);
2134 pcl->label = Safe_strdup(s);
2136 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2137 return ( (pCode *)pcl);
2142 /*-----------------------------------------------------------------*/
2143 /* newpBlock - create and return a pointer to a new pBlock */
2144 /*-----------------------------------------------------------------*/
2145 pBlock *newpBlock(void)
2150 PpB = Safe_calloc(1,sizeof(pBlock) );
2151 PpB->next = PpB->prev = NULL;
2153 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2154 PpB->tregisters = NULL;
2156 PpB->FlowTree = NULL;
2162 /*-----------------------------------------------------------------*/
2163 /* newpCodeChain - create a new chain of pCodes */
2164 /*-----------------------------------------------------------------*
2166 * This function will create a new pBlock and the pointer to the
2167 * pCode that is passed in will be the first pCode in the block.
2168 *-----------------------------------------------------------------*/
2171 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2174 pBlock *pB = newpBlock();
2176 pB->pcHead = pB->pcTail = pc;
2183 /*-----------------------------------------------------------------*/
2184 /* newpCodeOpLabel - Create a new label given the key */
2185 /* Note, a negative key means that the label is part of wild card */
2186 /* (and hence a wild card label) used in the pCodePeep */
2187 /* optimizations). */
2188 /*-----------------------------------------------------------------*/
2190 pCodeOp *newpCodeOpLabel(char *name, int key)
2193 static int label_key=-1;
2197 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2198 pcop->type = PO_LABEL;
2203 sprintf(s=buffer,"_%05d_DS_",key);
2205 s = name, key = label_key--;
2207 PCOLAB(pcop)->offset = 0;
2209 pcop->name = Safe_strdup(s);
2211 ((pCodeOpLabel *)pcop)->key = key;
2213 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2217 /*-----------------------------------------------------------------*/
2218 /*-----------------------------------------------------------------*/
2219 pCodeOp *newpCodeOpLit(int lit)
2225 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2226 pcop->type = PO_LITERAL;
2230 sprintf(s,"0x%02x",lit);
2232 pcop->name = Safe_strdup(s);
2235 ((pCodeOpLit *)pcop)->lit = lit;
2240 /*-----------------------------------------------------------------*/
2241 /*-----------------------------------------------------------------*/
2242 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2246 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2247 pcop->type = PO_IMMEDIATE;
2250 pcop->name = Safe_strdup(name);
2253 r = dirregWithName(name);
2257 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2258 PCOI(pcop)->rIdx = r->rIdx;
2260 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2261 PCOI(pcop)->rIdx = -1;
2263 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2268 PCOI(pcop)->index = index;
2269 PCOI(pcop)->offset = offset;
2270 PCOI(pcop)->_const = code_space;
2271 PCOI(pcop)->_function = is_func;
2276 /*-----------------------------------------------------------------*/
2277 /*-----------------------------------------------------------------*/
2278 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2284 if(!pcwb || !subtype) {
2285 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2289 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2290 pcop->type = PO_WILD;
2291 sprintf(s,"%%%d",id);
2292 pcop->name = Safe_strdup(s);
2294 PCOW(pcop)->id = id;
2295 PCOW(pcop)->pcwb = pcwb;
2296 PCOW(pcop)->subtype = subtype;
2297 PCOW(pcop)->matched = NULL;
2301 /*-----------------------------------------------------------------*/
2302 /* Find a symbol with matching name */
2303 /*-----------------------------------------------------------------*/
2304 static symbol *symFindWithName(memmap * map, const char *name)
2308 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2309 if (sym->rname && (strcmp(sym->rname,name)==0))
2315 /*-----------------------------------------------------------------*/
2316 /*-----------------------------------------------------------------*/
2317 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2322 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2323 pcop->type = PO_GPR_BIT;
2325 PCORB(pcop)->bit = ibit;
2326 PCORB(pcop)->inBitSpace = inBitSpace;
2328 if (name) r = regFindWithName(name);
2330 // Register has not been allocated - check for symbol information
2332 sym = symFindWithName(bit, name);
2333 if (!sym) sym = symFindWithName(sfrbit, name);
2334 if (!sym) sym = symFindWithName(sfr, name);
2336 r = allocNewDirReg(sym->etype,name);
2342 PCOR(pcop)->rIdx = r->rIdx;
2344 pcop->name = Safe_strdup(name);
2345 PCOR(pcop)->r = NULL;
2346 PCOR(pcop)->rIdx = 0;
2351 /*-----------------------------------------------------------------*
2352 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2354 * If rIdx >=0 then a specific register from the set of registers
2355 * will be selected. If rIdx <0, then a new register will be searched
2357 *-----------------------------------------------------------------*/
2359 pCodeOp *newpCodeOpReg(int rIdx)
2363 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2368 PCOR(pcop)->rIdx = rIdx;
2369 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2371 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2374 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2378 pcop->type = PCOR(pcop)->r->pc_type;
2383 pCodeOp *newpCodeOpRegFromStr(char *name)
2387 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2388 PCOR(pcop)->r = allocRegByName(name, 1);
2389 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2390 pcop->type = PCOR(pcop)->r->pc_type;
2391 pcop->name = PCOR(pcop)->r->name;
2396 pCodeOp *newpCodeOpStr(char *name)
2400 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2401 pcop->type = PO_STR;
2402 pcop->name = Safe_strdup(name);
2404 PCOS(pcop)->isPublic = 0;
2410 /*-----------------------------------------------------------------*/
2411 /*-----------------------------------------------------------------*/
2413 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2420 pcop = newpCodeOpBit(name, -1,0);
2424 pcop = newpCodeOpLit(-1);
2428 pcop = newpCodeOpLabel(NULL,-1);
2432 pcop = newpCodeOpReg(-1);
2435 case PO_GPR_POINTER:
2436 case PO_GPR_REGISTER:
2438 pcop = newpCodeOpRegFromStr(name);
2440 pcop = newpCodeOpReg(-1);
2444 pcop = newpCodeOpStr(name);
2448 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2451 pcop->name = Safe_strdup(name);
2459 /*-----------------------------------------------------------------*/
2460 /*-----------------------------------------------------------------*/
2461 void pCodeConstString(char *name, char *value)
2466 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2471 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2475 sprintf(buffer,"; %s = %s",name,value);
2476 for (i=strlen(buffer); i--; ) {
2477 unsigned char c = buffer[i];
2478 if (c=='\r' || c=='\n') {
2479 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2481 if (c=='\r') buffer[i+1] = 'r';
2482 else if (c=='\n') buffer[i+1] = 'n';
2486 addpCode2pBlock(pb,newpCodeCharP(buffer));
2487 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2490 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2496 /*-----------------------------------------------------------------*/
2497 /*-----------------------------------------------------------------*/
2498 void pCodeReadCodeTable(void)
2502 fprintf(stderr, " %s\n",__FUNCTION__);
2504 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2508 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2509 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2510 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2511 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2513 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2514 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2515 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2516 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2521 /*-----------------------------------------------------------------*/
2522 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2523 /*-----------------------------------------------------------------*/
2524 void addpCode2pBlock(pBlock *pb, pCode *pc)
2531 /* If this is the first pcode to be added to a block that
2532 * was initialized with a NULL pcode, then go ahead and
2533 * make this pcode the head and tail */
2534 pb->pcHead = pb->pcTail = pc;
2537 pb->pcTail->next = pc;
2539 pc->prev = pb->pcTail;
2546 /*-----------------------------------------------------------------*/
2547 /* addpBlock - place a pBlock into the pFile */
2548 /*-----------------------------------------------------------------*/
2549 void addpBlock(pBlock *pb)
2551 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2554 /* First time called, we'll pass through here. */
2555 //_ALLOC(the_pFile,sizeof(pFile));
2556 the_pFile = Safe_calloc(1,sizeof(pFile));
2557 the_pFile->pbHead = the_pFile->pbTail = pb;
2558 the_pFile->functions = NULL;
2562 the_pFile->pbTail->next = pb;
2563 pb->prev = the_pFile->pbTail;
2565 the_pFile->pbTail = pb;
2568 /*-----------------------------------------------------------------*/
2569 /* removepBlock - remove a pBlock from the pFile */
2570 /*-----------------------------------------------------------------*/
2571 void removepBlock(pBlock *pb)
2579 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2581 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2584 if(pbs == the_pFile->pbHead)
2585 the_pFile->pbHead = pbs->next;
2587 if (pbs == the_pFile->pbTail)
2588 the_pFile->pbTail = pbs->prev;
2591 pbs->next->prev = pbs->prev;
2594 pbs->prev->next = pbs->next;
2601 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2605 /*-----------------------------------------------------------------*/
2606 /* printpCode - write the contents of a pCode to a file */
2607 /*-----------------------------------------------------------------*/
2608 void printpCode(FILE *of, pCode *pc)
2619 fprintf(of,"warning - unable to print pCode\n");
2622 /*-----------------------------------------------------------------*/
2623 /* printpBlock - write the contents of a pBlock to a file */
2624 /*-----------------------------------------------------------------*/
2625 void printpBlock(FILE *of, pBlock *pb)
2635 for(pc = pb->pcHead; pc; pc = pc->next) {
2640 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2650 /*-----------------------------------------------------------------*/
2652 /* pCode processing */
2656 /*-----------------------------------------------------------------*/
2658 void unlinkpCode(pCode *pc)
2664 fprintf(stderr,"Unlinking: ");
2665 printpCode(stderr, pc);
2668 pc->prev->next = pc->next;
2670 pc->next->prev = pc->prev;
2673 /* RN: I believe this should be right here, but this did not
2674 * cure the bug I was hunting... */
2675 /* must keep labels -- attach to following instruction */
2676 if (isPCI(pc) && PCI(pc)->label && pc->next)
2678 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2681 pBranchAppend (pcnext->label, PCI(pc)->label);
2685 pc->prev = pc->next = NULL;
2689 /*-----------------------------------------------------------------*/
2690 /*-----------------------------------------------------------------*/
2692 static void genericDestruct(pCode *pc)
2698 /* For instructions, tell the register (if there's one used)
2699 * that it's no longer needed */
2700 regs *reg = getRegFromInstruction(pc);
2702 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2705 /* Instead of deleting the memory used by this pCode, mark
2706 * the object as bad so that if there's a pointer to this pCode
2707 * dangling around somewhere then (hopefully) when the type is
2708 * checked we'll catch it.
2713 addpCode2pBlock(pb_dead_pcodes, pc);
2720 /*-----------------------------------------------------------------*/
2721 /* Copies the pCodeInstruction flow pointer from source pCode */
2722 /*-----------------------------------------------------------------*/
2723 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2725 pCodeFlow *pcflow = 0;
2726 for (p=pcs; p; p=p->prev) {
2728 pcflow = PCI(p)->pcflow;
2732 pcflow = (pCodeFlow*)p;
2736 PCI(pcd)->pcflow = pcflow;
2739 /*-----------------------------------------------------------------*/
2740 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2741 /* into the pCode chain containing pc1 */
2742 /*-----------------------------------------------------------------*/
2743 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2749 pc2->next = pc1->next;
2751 pc1->next->prev = pc2;
2757 /* If this is an instrution type propogate the flow */
2759 CopyFlow(PCI(pc2),pc1);
2762 /*------------------------------------------------------------------*/
2763 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2764 /* into the pCode chain containing pc1 */
2765 /*------------------------------------------------------------------*/
2766 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2772 pc2->prev = pc1->prev;
2774 pc1->prev->next = pc2;
2780 /* If this is an instrution type propogate the flow */
2782 CopyFlow(PCI(pc2),pc1);
2785 /*-----------------------------------------------------------------*/
2786 /* pCodeOpCopy - copy a pcode operator */
2787 /*-----------------------------------------------------------------*/
2788 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2790 pCodeOp *pcopnew=NULL;
2795 switch(pcop->type) {
2798 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2799 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2800 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2801 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2806 /* Here we expand the wild card into the appropriate type: */
2807 /* By recursively calling pCodeOpCopy */
2808 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2809 if(PCOW(pcop)->matched)
2810 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2813 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2814 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2815 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2822 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2823 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2824 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2828 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2829 PCOI(pcopnew)->index = PCOI(pcop)->index;
2830 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2831 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2832 PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2836 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2837 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2838 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2843 pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2844 PCOR(pcopnew)->r = PCOR(pcop)->r;
2845 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2846 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2850 case PO_GPR_POINTER:
2851 case PO_GPR_REGISTER:
2855 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2856 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2857 PCOR(pcopnew)->r = PCOR(pcop)->r;
2858 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2859 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2860 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2864 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2865 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2866 PCOR(pcopnew)->r = PCOR(pcop)->r;
2867 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2868 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2871 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2872 case PO_SFR_REGISTER:
2880 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2881 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2885 pcopnew->type = pcop->type;
2887 pcopnew->name = Safe_strdup(pcop->name);
2889 pcopnew->name = NULL;
2894 /*-----------------------------------------------------------------*/
2895 /* popCopyReg - copy a pcode operator */
2896 /*-----------------------------------------------------------------*/
2897 pCodeOp *popCopyReg(pCodeOpReg *pc)
2901 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2902 pcor->pcop.type = pc->pcop.type;
2904 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2905 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2907 pcor->pcop.name = NULL;
2909 if (pcor->pcop.type == PO_IMMEDIATE){
2910 PCOL(pcor)->lit = PCOL(pc)->lit;
2913 pcor->rIdx = pc->rIdx;
2917 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2922 /*-----------------------------------------------------------------*/
2923 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2924 /*-----------------------------------------------------------------*/
2925 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2927 pCodeInstruction *new_pci;
2930 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2932 new_pci = PCI(newpCode(pci->op,pci->pcop));
2934 new_pci->pc.pb = pci->pc.pb;
2935 new_pci->from = pci->from;
2936 new_pci->to = pci->to;
2937 new_pci->label = pci->label;
2938 new_pci->pcflow = pci->pcflow;
2940 return PCODE(new_pci);
2943 /*-----------------------------------------------------------------*/
2944 /*-----------------------------------------------------------------*/
2945 void pCodeDeleteChain(pCode *f,pCode *t)
2950 DFPRINTF((stderr,"delete pCode:\n"));
2952 //f->print(stderr,f);
2953 //f->delete(f); this dumps core...
2958 /*-----------------------------------------------------------------*/
2959 /*-----------------------------------------------------------------*/
2960 void pBlockRegs(FILE *of, pBlock *pb)
2965 r = setFirstItem(pb->tregisters);
2967 r = setNextItem(pb->tregisters);
2972 /*-----------------------------------------------------------------*/
2973 /*-----------------------------------------------------------------*/
2974 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2979 int use_buffer = 1; // copy the string to the passed buffer pointer
2984 use_buffer = 0; // Don't bother copying the string to the buffer.
2988 switch(pcop->type) {
2992 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2995 //return PCOR(pcop)->r->name;
2999 if (PCOR(pcop)->r->type == REG_STK)
3000 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3002 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3005 SAFE_snprintf(&buffer,&size,"%s",r->name);
3014 if(PCOI(pcop)->_const) {
3016 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3017 switch(PCOI(pcop)->offset) {
3019 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3022 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3025 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3026 assert ( !"offset too large" );
3027 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3030 8 * PCOI(pcop)->offset );
3033 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3035 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) {
3036 SAFE_snprintf(&s,&size,"(%s + %d)",
3040 switch(PCOI(pcop)->offset) {
3042 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3045 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3048 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3049 assert ( !"offset too large" );
3050 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3060 //size = sizeof(buffer);
3061 if( PCOR(pcop)->instance) {
3062 SAFE_snprintf(&s,&size,"(%s + %d)",
3064 PCOR(pcop)->instance );
3065 //fprintf(stderr,"PO_DIR %s\n",buffer);
3067 SAFE_snprintf(&s,&size,"%s",pcop->name);
3073 if(PCOLAB(pcop)->offset == 1)
3074 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3076 SAFE_snprintf(&s,&size,"%s",pcop->name);
3083 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3086 return PCOR(pcop)->r->name;
3089 /* fall through to the default case */
3093 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3101 printf("PIC port internal warning: (%s:%d) %s not found\n",
3106 return "NO operand";
3110 /*-----------------------------------------------------------------*/
3111 /*-----------------------------------------------------------------*/
3112 static char *get_op_from_instruction( pCodeInstruction *pcc)
3116 return get_op(pcc->pcop,NULL,0);
3118 return ("ERROR Null: get_op_from_instruction");
3122 /*-----------------------------------------------------------------*/
3123 /*-----------------------------------------------------------------*/
3124 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3126 fprintf(of,"pcodeopprint- not implemented\n");
3129 /*-----------------------------------------------------------------*/
3130 /* pCode2str - convert a pCode instruction to string */
3131 /*-----------------------------------------------------------------*/
3132 char *pCode2str(char *str, size_t size, pCode *pc)
3140 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3142 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3144 if(PCI(pc)->isBitInst) {
3145 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3146 char *name = PCI(pc)->pcop->name;
3148 name = PCOR(PCI(pc)->pcop)->r->name;
3149 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3150 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3152 SAFE_snprintf(&s,&size,"%s,%d", name,
3153 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3154 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3155 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3157 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3158 //PCI(pc)->pcop->t.bit );
3160 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3161 if( PCI(pc)->num_ops == 2)
3162 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3164 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3166 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3167 if( PCI(pc)->num_ops == 2)
3168 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3175 /* assuming that comment ends with a \n */
3176 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3180 /* assuming that inline code ends with a \n */
3181 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3185 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3188 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3191 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3194 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3197 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3198 SAFE_snprintf(&s,&size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3201 if(PCAD(pc)->directive) {
3202 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3203 } else if(PCAD(pc)->arg) {
3204 /* special case to handle inline labels without a tab */
3205 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3210 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3216 /*-----------------------------------------------------------------*/
3217 /* genericPrint - the contents of a pCode to a file */
3218 /*-----------------------------------------------------------------*/
3219 static void genericPrint(FILE *of, pCode *pc)
3226 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3230 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3234 // If the opcode has a label, print that first
3237 pCodeInstruction *pci = PCI(pc);
3238 pBranch *pbl = pci->label;
3239 while(pbl && pbl->pc) {
3240 if(pbl->pc->type == PC_LABEL)
3241 pCodePrintLabel(of, pbl->pc);
3246 genericPrint(of,PCODE(pci->cline));
3249 pCode2str(str, 256, pc);
3251 fprintf(of,"%s",str);
3255 pCodeOpReg *pcor = PCOR(pci->pcop);
3256 fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3258 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3259 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3260 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3265 pBranch *dpb = pc->to; // debug
3267 switch ( dpb->pc->type) {
3269 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3272 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3275 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3278 fprintf(of, "\t;flow");
3292 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3293 if(PCW(pc)->pci.label)
3294 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3296 if(PCW(pc)->operand) {
3297 fprintf(of,";\toperand ");
3298 pCodeOpPrint(of,PCW(pc)->operand );
3304 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3305 if(PCFL(pc)->ancestor)
3306 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3312 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3313 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3318 pBranch *pbl = PCAD(pc)->pci.label;
3319 while(pbl && pbl->pc) {
3320 if(pbl->pc->type == PC_LABEL)
3321 pCodePrintLabel(of, pbl->pc);
3325 if(PCAD(pc)->directive) {
3326 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3329 /* special case to handle inline labels without tab */
3330 fprintf(of, "%s\n", PCAD(pc)->arg);
3336 fprintf(of,"unknown pCode type %d\n",pc->type);
3340 /*-----------------------------------------------------------------*/
3341 /* pCodePrintFunction - prints function begin/end */
3342 /*-----------------------------------------------------------------*/
3344 static void pCodePrintFunction(FILE *of, pCode *pc)
3350 if( ((pCodeFunction *)pc)->modname)
3351 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3353 if(PCF(pc)->fname) {
3354 pBranch *exits = PCF(pc)->to;
3356 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3359 exits = exits->next;
3362 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3365 if((PCF(pc)->from &&
3366 PCF(pc)->from->pc->type == PC_FUNCTION &&
3367 PCF(PCF(pc)->from->pc)->fname) )
3368 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3370 fprintf(of,"; exit point [can't find entry point]\n");
3373 /*-----------------------------------------------------------------*/
3374 /* pCodePrintLabel - prints label */
3375 /*-----------------------------------------------------------------*/
3377 static void pCodePrintLabel(FILE *of, pCode *pc)
3384 fprintf(of,"%s\n",PCL(pc)->label);
3385 else if (PCL(pc)->key >=0)
3386 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3388 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3392 /*-----------------------------------------------------------------*/
3393 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3394 /* remove it if it is found. */
3395 /*-----------------------------------------------------------------*/
3396 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3402 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3403 b = PCI(pcl)->label;
3405 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3409 //fprintf (stderr, "%s \n",__FUNCTION__);
3410 //pcl->print(stderr,pcl);
3411 //pc->print(stderr,pc);
3414 //fprintf (stderr, "found label\n");
3418 bprev->next = b->next; /* Not first pCode in chain */
3422 PCI(pcl)->label = b->next; /* First pCode in chain */
3425 return; /* A label can't occur more than once */
3432 /*-----------------------------------------------------------------*/
3433 /*-----------------------------------------------------------------*/
3434 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3453 /*-----------------------------------------------------------------*/
3454 /* pBranchLink - given two pcodes, this function will link them */
3455 /* together through their pBranches */
3456 /*-----------------------------------------------------------------*/
3457 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3461 // Declare a new branch object for the 'from' pCode.
3463 //_ALLOC(b,sizeof(pBranch));
3464 b = Safe_calloc(1,sizeof(pBranch));
3465 b->pc = PCODE(t); // The link to the 'to' pCode.
3468 f->to = pBranchAppend(f->to,b);
3470 // Now do the same for the 'to' pCode.
3472 //_ALLOC(b,sizeof(pBranch));
3473 b = Safe_calloc(1,sizeof(pBranch));
3477 t->from = pBranchAppend(t->from,b);
3482 /*-----------------------------------------------------------------*/
3483 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3485 /*-----------------------------------------------------------------*/
3486 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3499 /*-----------------------------------------------------------------*/
3500 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3501 /*-----------------------------------------------------------------*/
3502 static void pCodeUnlink(pCode *pc)
3507 if(!pc->prev || !pc->next) {
3508 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3512 /* first remove the pCode from the chain */
3513 pc->prev->next = pc->next;
3514 pc->next->prev = pc->prev;
3516 /* Now for the hard part... */
3518 /* Remove the branches */
3522 pc1 = pb1->pc; /* Get the pCode that branches to the
3523 * one we're unlinking */
3525 /* search for the link back to this pCode (the one we're
3527 if(pb2 = pBranchFind(pc1->to,pc)) {
3528 pb2->pc = pc->to->pc; // make the replacement
3530 /* if the pCode we're unlinking contains multiple 'to'
3531 * branches (e.g. this a skip instruction) then we need
3532 * to copy these extra branches to the chain. */
3534 pBranchAppend(pb2, pc->to->next);
3543 /*-----------------------------------------------------------------*/
3544 /*-----------------------------------------------------------------*/
3546 static void genericAnalyze(pCode *pc)
3556 // Go through the pCodes that are in pCode chain and link
3557 // them together through the pBranches. Note, the pCodes
3558 // are linked together as a contiguous stream like the
3559 // assembly source code lines. The linking here mimics this
3560 // except that comments are not linked in.
3562 pCode *npc = pc->next;
3564 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3565 pBranchLink(pc,npc);
3570 /* reached the end of the pcode chain without finding
3571 * an instruction we could link to. */
3575 fprintf(stderr,"analyze PC_FLOW\n");
3579 fprintf(stderr,";A bad pCode is being used\n");
3585 /*-----------------------------------------------------------------*/
3586 /*-----------------------------------------------------------------*/
3587 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3591 if(pc->type == PC_LABEL) {
3592 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3595 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3596 pbr = PCI(pc)->label;
3598 if(pbr->pc->type == PC_LABEL) {
3599 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3609 /*-----------------------------------------------------------------*/
3610 /*-----------------------------------------------------------------*/
3611 int checkLabel(pCode *pc)
3615 if(pc && isPCI(pc)) {
3616 pbr = PCI(pc)->label;
3618 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3628 /*-----------------------------------------------------------------*/
3629 /* findLabelinpBlock - Search the pCode for a particular label */
3630 /*-----------------------------------------------------------------*/
3631 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3638 for(pc = pb->pcHead; pc; pc = pc->next)
3639 if(compareLabel(pc,pcop_label))
3645 /*-----------------------------------------------------------------*/
3646 /* findLabel - Search the pCode for a particular label */
3647 /*-----------------------------------------------------------------*/
3648 pCode * findLabel(pCodeOpLabel *pcop_label)
3656 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3657 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3661 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3665 /*-----------------------------------------------------------------*/
3666 /* findNextpCode - given a pCode, find the next of type 'pct' */
3667 /* in the linked list */
3668 /*-----------------------------------------------------------------*/
3669 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3682 /*-----------------------------------------------------------------*/
3683 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3684 /* in the linked list */
3685 /*-----------------------------------------------------------------*/
3686 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3690 if(pc->type == pct) {
3692 static unsigned int stop;
3694 stop++; // Place break point here
3705 /*-----------------------------------------------------------------*/
3706 /* findNextInstruction - given a pCode, find the next instruction */
3707 /* in the linked list */
3708 /*-----------------------------------------------------------------*/
3709 pCode * findNextInstruction(pCode *pci)
3714 if((pc->type == PC_OPCODE)
3715 || (pc->type == PC_WILD)
3716 || (pc->type == PC_ASMDIR))
3720 fprintf(stderr,"findNextInstruction: ");
3721 printpCode(stderr, pc);
3726 //fprintf(stderr,"Couldn't find instruction\n");
3730 /*-----------------------------------------------------------------*/
3731 /* findNextInstruction - given a pCode, find the next instruction */
3732 /* in the linked list */
3733 /*-----------------------------------------------------------------*/
3734 pCode * findPrevInstruction(pCode *pci)
3740 if((pc->type == PC_OPCODE)
3741 || (pc->type == PC_WILD)
3742 || (pc->type == PC_ASMDIR))
3747 fprintf(stderr,"pic16_findPrevInstruction: ");
3748 printpCode(stderr, pc);
3753 //fprintf(stderr,"Couldn't find instruction\n");
3757 /*-----------------------------------------------------------------*/
3758 /* findFunctionEnd - given a pCode find the end of the function */
3759 /* that contains it */
3760 /*-----------------------------------------------------------------*/
3761 pCode * findFunctionEnd(pCode *pc)
3764 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3770 fprintf(stderr,"Couldn't find function end\n");
3775 /*-----------------------------------------------------------------*/
3776 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3777 /* instruction with which it is associated. */
3778 /*-----------------------------------------------------------------*/
3779 static void AnalyzeLabel(pCode *pc)
3788 static void AnalyzeGOTO(pCode *pc)
3791 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3795 static void AnalyzeSKIP(pCode *pc)
3798 pBranchLink(pc,findNextInstruction(pc->next));
3799 pBranchLink(pc,findNextInstruction(pc->next->next));
3803 static void AnalyzeRETURN(pCode *pc)
3806 // branch_link(pc,findFunctionEnd(pc->next));
3812 /*-----------------------------------------------------------------*/
3813 /*-----------------------------------------------------------------*/
3814 regs * getRegFromInstruction(pCode *pc)
3820 PCI(pc)->num_ops == 0 )
3823 switch(PCI(pc)->pcop->type) {
3826 return PCOR(PCI(pc)->pcop)->r;
3830 return PCOR(PCI(pc)->pcop)->r;
3833 r = PCOI(PCI(pc)->pcop)->r;
3836 return dirregWithName(PCI(pc)->pcop->name);
3839 r = PCOR(PCI(pc)->pcop)->r;
3842 return dirregWithName(PCI(pc)->pcop->name);
3844 case PO_GPR_REGISTER:
3846 r = PCOR(PCI(pc)->pcop)->r;
3849 return dirregWithName(PCI(pc)->pcop->name);
3861 /*-----------------------------------------------------------------*/
3862 /*-----------------------------------------------------------------*/
3864 void AnalyzepBlock(pBlock *pb)
3871 /* Find all of the registers used in this pBlock
3872 * by looking at each instruction and examining it's
3875 for(pc = pb->pcHead; pc; pc = pc->next) {
3877 /* Is this an instruction with operands? */
3878 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3880 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3881 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3883 /* Loop through all of the registers declared so far in
3884 this block and see if we find this one there */
3886 regs *r = setFirstItem(pb->tregisters);
3889 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3890 PCOR(PCI(pc)->pcop)->r = r;
3893 r = setNextItem(pb->tregisters);
3897 /* register wasn't found */
3898 //r = Safe_calloc(1, sizeof(regs));
3899 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3900 //addSet(&pb->tregisters, r);
3901 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3902 //PCOR(PCI(pc)->pcop)->r = r;
3903 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3905 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3908 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3909 if(PCOR(PCI(pc)->pcop)->r) {
3910 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3911 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3913 if(PCI(pc)->pcop->name)
3914 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3916 fprintf(stderr,"ERROR: NULL register\n");
3925 /*-----------------------------------------------------------------*/
3927 /*-----------------------------------------------------------------*/
3928 void InsertpFlow(pCode *pc, pCode **pflow)
3931 PCFL(*pflow)->end = pc;
3933 if(!pc || !pc->next)
3936 *pflow = newpCodeFlow();
3937 pCodeInsertAfter(pc, *pflow);
3940 /*-----------------------------------------------------------------*/
3941 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3942 /* the flow blocks. */
3944 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3945 * point the instruction flow changes.
3947 /*-----------------------------------------------------------------*/
3948 void BuildFlow(pBlock *pb)
3951 pCode *last_pci=NULL;
3958 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3959 /* Insert a pCodeFlow object at the beginning of a pBlock */
3961 InsertpFlow(pb->pcHead, &pflow);
3963 //pflow = newpCodeFlow(); /* Create a new Flow object */
3964 //pflow->next = pb->pcHead; /* Make the current head the next object */
3965 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3966 //pb->pcHead = pflow; /* Make the Flow object the head */
3969 for( pc = findNextInstruction(pb->pcHead);
3971 pc=findNextInstruction(pc)) {
3974 PCI(pc)->pcflow = PCFL(pflow);
3976 //fprintf(stderr," build: ");
3977 //pflow->print(stderr,pflow);
3979 if( PCI(pc)->isSkip) {
3981 /* The two instructions immediately following this one
3982 * mark the beginning of a new flow segment */
3984 while(pc && PCI(pc)->isSkip) {
3986 PCI(pc)->pcflow = PCFL(pflow);
3990 InsertpFlow(pc, &pflow);
3991 pc=findNextInstruction(pc->next);
3999 PCI(pc)->pcflow = PCFL(pflow);
4001 InsertpFlow(pc, &pflow);
4003 } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next))) {
4005 InsertpFlow(pc, &pflow);
4008 } else if (checkLabel(pc)) {
4010 /* This instruction marks the beginning of a
4011 * new flow segment */
4016 /* If the previous pCode is not a flow object, then
4017 * insert a new flow object. (This check prevents
4018 * two consecutive flow objects from being insert in
4019 * the case where a skip instruction preceeds an
4020 * instruction containing a label.) */
4022 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4023 InsertpFlow(findPrevInstruction(pc->prev), &pflow);
4025 PCI(pc)->pcflow = PCFL(pflow);
4032 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4034 PCFL(pflow)->end = pb->pcTail;
4037 /*-------------------------------------------------------------------*/
4038 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4039 /* the flow blocks. */
4041 * unBuildFlow removes pCodeFlow objects from a pCode chain
4043 /*-----------------------------------------------------------------*/
4044 void unBuildFlow(pBlock *pb)
4059 if(PCI(pc)->pcflow) {
4060 //free(PCI(pc)->pcflow);
4061 PCI(pc)->pcflow = NULL;
4064 } else if(isPCFL(pc) )
4073 /*-----------------------------------------------------------------*/
4074 /*-----------------------------------------------------------------*/
4075 void dumpCond(int cond)
4078 static char *pcc_str[] = {
4092 int ncond = sizeof(pcc_str) / sizeof(char *);
4095 fprintf(stderr, "0x%04X\n",cond);
4097 for(i=0,j=1; i<ncond; i++, j<<=1)
4099 fprintf(stderr, " %s\n",pcc_str[i]);
4103 /*-----------------------------------------------------------------*/
4104 /*-----------------------------------------------------------------*/
4105 void FlowStats(pCodeFlow *pcflow)
4113 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4115 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4118 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4123 fprintf(stderr, " FlowStats inCond: ");
4124 dumpCond(pcflow->inCond);
4125 fprintf(stderr, " FlowStats outCond: ");
4126 dumpCond(pcflow->outCond);
4130 /*-----------------------------------------------------------------*
4131 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4132 * if it affects the banking bits.
4134 * return: -1 == Banking bits are unaffected by this pCode.
4136 * return: > 0 == Banking bits are affected.
4138 * If the banking bits are affected, then the returned value describes
4139 * which bits are affected and how they're affected. The lower half
4140 * of the integer maps to the bits that are affected, the upper half
4141 * to whether they're set or cleared.
4143 *-----------------------------------------------------------------*/
4145 #define SET_BANK_BIT (1 << 16)
4146 #define CLR_BANK_BIT 0
4148 static int isBankInstruction(pCode *pc)
4156 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4158 // Check to see if the register banks are changing
4159 if(PCI(pc)->isModReg) {
4161 pCodeOp *pcop = PCI(pc)->pcop;
4162 switch(PCI(pc)->op) {
4165 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4166 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4167 return SET_BANK_BIT | PIC_RP0_BIT;
4170 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4171 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4172 return CLR_BANK_BIT | PIC_RP0_BIT;
4177 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4178 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4179 return CLR_BANK_BIT | PIC_RP1_BIT;
4181 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4182 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4183 return CLR_BANK_BIT | PIC_RP1_BIT;
4187 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4188 //genericPrint(stderr, pc);
4199 /*-----------------------------------------------------------------*/
4200 /*-----------------------------------------------------------------*/
4202 static void FillFlow(pCodeFlow *pcflow)
4210 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4212 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4215 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4222 isBankInstruction(pc);
4224 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4227 fprintf(stderr, " FillFlow - Bad end of flow\n");
4229 fprintf(stderr, " FillFlow - Ending flow with\n ");
4230 pc->print(stderr,pc);
4233 fprintf(stderr, " FillFlow inCond: ");
4234 dumpCond(pcflow->inCond);
4235 fprintf(stderr, " FillFlow outCond: ");
4236 dumpCond(pcflow->outCond);
4241 /*-----------------------------------------------------------------*/
4242 /*-----------------------------------------------------------------*/
4243 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4245 pCodeFlowLink *fromLink, *toLink;
4247 if(!from || !to || !to->pcflow || !from->pcflow)
4250 fromLink = newpCodeFlowLink(from->pcflow);
4251 toLink = newpCodeFlowLink(to->pcflow);
4253 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4254 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4258 /*-----------------------------------------------------------------*
4259 * void LinkFlow(pBlock *pb)
4261 * In BuildFlow, the PIC code has been partitioned into contiguous
4262 * non-branching segments. In LinkFlow, we determine the execution
4263 * order of these segments. For example, if one of the segments ends
4264 * with a skip, then we know that there are two possible flow segments
4265 * to which control may be passed.
4266 *-----------------------------------------------------------------*/
4267 void LinkFlow(pBlock *pb)
4273 //fprintf(stderr,"linkflow \n");
4275 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4277 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4280 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4282 //fprintf(stderr," link: ");
4283 //pcflow->print(stderr,pcflow);
4285 //FillFlow(PCFL(pcflow));
4287 pc = PCFL(pcflow)->end;
4289 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4290 if(isPCI_SKIP(pc)) {
4291 //fprintf(stderr, "ends with skip\n");
4292 //pc->print(stderr,pc);
4293 pct=findNextInstruction(pc->next);
4294 LinkFlow_pCode(PCI(pc),PCI(pct));
4295 pct=findNextInstruction(pct->next);
4296 LinkFlow_pCode(PCI(pc),PCI(pct));
4300 if(isPCI_BRANCH(pc)) {
4301 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4303 //fprintf(stderr, "ends with branch\n ");
4304 //pc->print(stderr,pc);
4306 if(!(pcol && isPCOLAB(pcol))) {
4307 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4308 pc->print(stderr,pc);
4309 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4314 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4315 LinkFlow_pCode(PCI(pc),PCI(pct));
4317 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4318 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4319 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4325 //fprintf(stderr, "ends with non-branching instruction:\n");
4326 //pc->print(stderr,pc);
4328 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4334 //fprintf(stderr, "ends with unknown\n");
4335 //pc->print(stderr,pc);
4339 //fprintf(stderr, "ends with nothing: ERROR\n");
4343 /*-----------------------------------------------------------------*/
4344 /*-----------------------------------------------------------------*/
4346 /*-----------------------------------------------------------------*/
4347 /*-----------------------------------------------------------------*/
4348 int isPCinFlow(pCode *pc, pCode *pcflow)
4354 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4357 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4363 /*-----------------------------------------------------------------*/
4364 /*-----------------------------------------------------------------*/
4366 static void BanksUsedFlow2(pCode *pcflow)
4375 if(!isPCFL(pcflow)) {
4376 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4380 pc = findNextInstruction(pcflow->next);
4382 PCFL(pcflow)->lastBank = -1;
4384 while(isPCinFlow(pc,pcflow)) {
4386 int bank_selected = isBankInstruction(pc);
4388 //if(PCI(pc)->pcflow)
4389 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4391 if(bank_selected > 0) {
4392 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4394 // This instruction is modifying banking bits before accessing registers
4396 PCFL(pcflow)->firstBank = -1;
4398 if(PCFL(pcflow)->lastBank == -1)
4399 PCFL(pcflow)->lastBank = 0;
4401 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4402 if(bank_selected & SET_BANK_BIT)
4403 PCFL(pcflow)->lastBank |= bank;
4407 reg = getRegFromInstruction(pc);
4409 if(reg && !isREGinBank(reg, bank)) {
4410 int allbanks = REGallBanks(reg);
4412 PCFL(pcflow)->firstBank = allbanks;
4414 PCFL(pcflow)->lastBank = allbanks;
4421 pc = findNextInstruction(pc->next);
4424 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4425 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4428 /*-----------------------------------------------------------------*/
4429 /*-----------------------------------------------------------------*/
4431 static void BanksUsedFlow(pBlock *pb)
4436 //pb->pcHead->print(stderr, pb->pcHead);
4438 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4439 //pcflow->print(stderr,pcflow);
4441 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4443 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4445 BanksUsedFlow2(pcflow);
4451 /*-----------------------------------------------------------------*/
4452 /* Inserts a new pCodeInstruction before an existing one */
4453 /*-----------------------------------------------------------------*/
4454 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4457 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4459 /* Move the label, if there is one */
4462 new_pci->label = pci->label;
4466 /* Move the C code comment, if there is one */
4469 new_pci->cline = pci->cline;
4473 /* The new instruction has the same pcflow block */
4474 new_pci->pcflow = pci->pcflow;
4478 /*-----------------------------------------------------------------*/
4479 /*-----------------------------------------------------------------*/
4480 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4484 new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4486 insertPCodeInstruction(pci, PCI(new_pc));
4489 /*-----------------------------------------------------------------*/
4490 /*-----------------------------------------------------------------*/
4491 static void insertBankSel(pCodeInstruction *pci, const char *name)
4495 pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4496 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4497 if (pcop->name == 0)
4498 pcop->name = strdup(name);
4499 new_pc = newpCode(POC_BANKSEL, pcop);
4501 insertPCodeInstruction(pci, PCI(new_pc));
4504 /*-----------------------------------------------------------------*/
4505 /* If the register is a fixed known addess then we can assign the */
4506 /* bank selection bits. Otherwise the linker is going to assign */
4507 /* the register location and thus has to set bank selection bits */
4508 /* through the banksel directive. */
4509 /* One critical assumption here is that within this C module all */
4510 /* the locally allocated registers are in the same udata sector. */
4511 /* Therefore banksel is only called for external registers or the */
4512 /* first time a local register is encountered. */
4513 /*-----------------------------------------------------------------*/
4514 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4515 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4518 int a = reg->alias>>7;
4520 return cur_bank; // This register is available in all banks
4521 } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4522 return cur_bank; // This register is available in banks 0 & 1
4524 if (reg->address&0x80) {
4525 if ((cur_bank==1)||(cur_bank==3)) {
4526 return cur_bank; // This register is available in banks 1 & 3
4529 if ((cur_bank==0)||(cur_bank==1)) {
4530 return cur_bank; // This register is available in banks 0 & 2
4536 if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4538 LastRegIdx = reg->rIdx;
4542 bank = REG_BANK(reg);
4543 } else if (reg->isExtern) {
4544 bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4546 bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4548 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.
4549 return 'L'; // Local registers are presumed to be in same linker assigned bank
4550 } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4551 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4552 } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4553 insertBankSel(pci, reg->name); // Let linker choose the bank selection
4554 } 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
4555 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4556 if (getMaxRam()&0x100)
4557 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4558 } else { // Current bank and new register banks known - can set bank bits
4559 switch((cur_bank^bank) & 3) {
4563 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4566 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4569 insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4570 if (getMaxRam()&0x100)
4571 insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4579 /*-----------------------------------------------------------------*/
4580 /* Check for bank selection pcodes instructions and modify */
4581 /* cur_bank to match. */
4582 /*-----------------------------------------------------------------*/
4583 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4585 if (isSTATUS_REG(reg)) {
4587 if (PCI(pc)->op == POC_BCF) {
4588 int old_bank = *cur_bank;
4589 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4590 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4591 if (*cur_bank & ~(0x3))
4594 *cur_bank = *cur_bank&0x2;
4595 LastRegIdx = reg->rIdx;
4596 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4597 /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4598 if (*cur_bank & ~(0x3))
4601 *cur_bank = *cur_bank&0x1;
4602 LastRegIdx = reg->rIdx;
4604 return old_bank != *cur_bank;
4607 if (PCI(pc)->op == POC_BSF) {
4608 int old_bank = *cur_bank;
4609 if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4610 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4611 if (*cur_bank & ~(0x3))
4614 *cur_bank = (*cur_bank&0x2) | 0x1;
4615 LastRegIdx = reg->rIdx;
4616 } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4617 /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4618 if (*cur_bank & ~(0x3))
4621 *cur_bank = (*cur_bank&0x1) | 0x2;
4622 LastRegIdx = reg->rIdx;
4624 return old_bank != *cur_bank;
4627 } else if (PCI(pc)->op == POC_BANKSEL) {
4628 int old_bank = *cur_bank;
4629 regs *r = PCOR(PCI(pc)->pcop)->r;
4630 *cur_bank = (!r || r->isExtern) ? 'E' : 'L';
4631 LastRegIdx = reg->rIdx;
4632 return old_bank != *cur_bank;
4638 /*-----------------------------------------------------------------*/
4639 /* Set bank selection if necessary */
4640 /*-----------------------------------------------------------------*/
4641 static int DoBankSelect(pCode *pc, int cur_bank) {
4649 pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4650 LastRegIdx = -1; /* do not know which register is touched in the called function... */
4651 if (pcf && isPCF(pcf)) {
4653 int rbank = 'U'; // Undetermined
4654 FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4655 // Check all the returns to work out what bank is selected
4656 for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4658 if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4660 rbank = PCI(pcfr)->pcflow->lastBank;
4662 if (rbank != PCI(pcfr)->pcflow->lastBank)
4663 return -1; // Unknown bank - multiple returns with different banks
4668 return -1; // Unknown bank
4670 } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4671 /* Extern functions may use registers in different bank - must call banksel */
4672 return -1; /* Unknown bank */
4678 if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4679 return -1; /* New bank unknown - linkers choice. */
4682 reg = getRegFromInstruction(pc);
4684 if (IsBankChange(pc,reg,&cur_bank))
4686 if (!isPCI_LIT(pc)) {
4688 /* Examine the instruction before this one to make sure it is
4689 * not a skip type instruction */
4690 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4692 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4693 cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4695 cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4697 if (!PCI(pc)->pcflow)
4698 fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4700 PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4706 /*-----------------------------------------------------------------*/
4707 /*-----------------------------------------------------------------*/
4709 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4717 pc = findNextInstruction(pcfl->pc.next);
4719 while(isPCinFlow(pc,PCODE(pcfl))) {
4721 cur_bank = DoBankSelect(pc,cur_bank);
4723 pc = findNextInstruction(pc->next);
4727 if(pcprev && cur_bank) {
4728 // Set bank state to unknown at the end of each flow block
4734 /*-----------------------------------------------------------------*/
4735 /*int compareBankFlow - compare the banking requirements between */
4737 /*-----------------------------------------------------------------*/
4739 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4742 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4745 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4748 if(pcflow->firstBank == -1)
4752 if(pcflowLink->pcflow->firstBank == -1) {
4753 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
4754 pcflowLink->pcflow->to :
4755 pcflowLink->pcflow->from);
4756 return compareBankFlow(pcflow, pctl, toORfrom);
4760 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4763 pcflowLink->bank_conflict++;
4764 pcflowLink->pcflow->FromConflicts++;
4765 pcflow->ToConflicts++;
4768 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4771 pcflowLink->bank_conflict++;
4772 pcflowLink->pcflow->ToConflicts++;
4773 pcflow->FromConflicts++;
4777 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4778 pcflowLink->pcflow->pc.seq,
4779 pcflowLink->pcflow->FromConflicts,
4780 pcflowLink->pcflow->ToConflicts);
4786 /*-----------------------------------------------------------------*/
4787 /*-----------------------------------------------------------------*/
4789 void FixBankFlow(pBlock *pb)
4793 pCodeFlowLink *pcfl;
4795 pCode *pcflow_max_To=NULL;
4796 pCode *pcflow_max_From=NULL;
4797 int max_ToConflicts=0;
4798 int max_FromConflicts=0;
4800 /fprintf(stderr,"Fix Bank flow \n");
4801 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4805 First loop through all of the flow objects in this pcode block
4806 and fix the ones that have banking conflicts between the
4810 //fprintf(stderr, "FixBankFlow - Phase 1\n");
4812 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4814 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4816 if(!isPCFL(pcflow)) {
4817 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4821 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
4822 PCFL(pcflow)->firstBank >= 0 &&
4823 PCFL(pcflow)->lastBank >= 0 ) {
4825 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4826 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4828 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4829 BanksUsedFlow2(pcflow);
4834 //fprintf(stderr, "FixBankFlow - Phase 2\n");
4836 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4838 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4843 if(!isPCFL(pcflow)) {
4844 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4848 PCFL(pcflow)->FromConflicts = 0;
4849 PCFL(pcflow)->ToConflicts = 0;
4854 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4855 pcfl = setFirstItem(PCFL(pcflow)->from);
4858 pc = PCODE(pcfl->pcflow);
4861 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4862 pc->print(stderr,pc);
4865 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4868 pcfl=setNextItem(PCFL(pcflow)->from);
4871 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4872 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4874 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4875 BanksUsedFlow2(pcflow);
4877 continue; / * Don't need to check the flow from here - it's already been fixed * /
4884 pcfl = setFirstItem(PCFL(pcflow)->to);
4887 pc = PCODE(pcfl->pcflow);
4889 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4890 pc->print(stderr,pc);
4893 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4896 pcfl=setNextItem(PCFL(pcflow)->to);
4899 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4900 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4902 FixRegisterBankingInFlow(PCFL(pcflow),-1);
4903 BanksUsedFlow2(pcflow);
4908 Loop through the flow objects again and find the ones with the
4912 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4914 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4916 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4917 pcflow_max_To = pcflow;
4919 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4920 pcflow_max_From = pcflow;
4924 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4925 PCFL(pcflow_max_To)->pc.seq,
4926 PCFL(pcflow_max_To)->ToConflicts);
4929 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4930 PCFL(pcflow_max_From)->pc.seq,
4931 PCFL(pcflow_max_From)->FromConflicts);
4936 /*-----------------------------------------------------------------*/
4937 /*-----------------------------------------------------------------*/
4938 void DumpFlow(pBlock *pb)
4942 pCodeFlowLink *pcfl;
4945 fprintf(stderr,"Dump flow \n");
4946 pb->pcHead->print(stderr, pb->pcHead);
4948 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4949 pcflow->print(stderr,pcflow);
4951 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4953 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4955 if(!isPCFL(pcflow)) {
4956 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4959 fprintf(stderr,"dumping: ");
4960 pcflow->print(stderr,pcflow);
4961 FlowStats(PCFL(pcflow));
4963 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4965 pc = PCODE(pcfl->pcflow);
4967 fprintf(stderr, " from seq %d:\n",pc->seq);
4969 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4970 pc->print(stderr,pc);
4975 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4977 pc = PCODE(pcfl->pcflow);
4979 fprintf(stderr, " to seq %d:\n",pc->seq);
4981 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4982 pc->print(stderr,pc);
4991 /*-----------------------------------------------------------------*/
4992 /*-----------------------------------------------------------------*/
4993 int OptimizepBlock(pBlock *pb)
4998 if(!pb || !peepOptimizing)
5001 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5003 for(pc = pb->pcHead; pc; pc = pc->next)
5004 matches += pCodePeepMatchRule(pc);
5007 pc = findNextInstruction(pb->pcHead);
5015 if(pCodePeepMatchRule(pc)) {
5020 pc = findNextInstruction(pcprev->next);
5022 pc = findNextInstruction(pb->pcHead);
5024 pc = findNextInstruction(pc->next);
5028 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5033 /*-----------------------------------------------------------------*/
5034 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5035 /*-----------------------------------------------------------------*/
5036 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5040 for(pc = pcs; pc; pc = pc->next) {
5042 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
5044 (PCI(pc)->pcop->type == PO_LABEL) &&
5045 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5052 /*-----------------------------------------------------------------*/
5053 /*-----------------------------------------------------------------*/
5054 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5061 (PCI(pc)->pcop->type == PO_LABEL)) {
5063 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5065 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5067 free(pcol->pcop.name);
5069 /* If the key is negative, then we (probably) have a label to
5070 * a function and the name is already defined */
5073 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5077 //sprintf(buffer,"_%05d_DS_",pcl->key);
5079 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5081 pcol->pcop.name = Safe_strdup(s);
5082 pcol->key = pcl->key;
5083 //pc->print(stderr,pc);
5090 /*-----------------------------------------------------------------*/
5091 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5092 /* pCode chain if they're not used. */
5093 /*-----------------------------------------------------------------*/
5094 void pBlockRemoveUnusedLabels(pBlock *pb)
5096 pCode *pc; pCodeLabel *pcl;
5101 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
5103 pBranch *pbr = PCI(pc)->label;
5104 if(pbr && pbr->next) {
5105 pCode *pcd = pb->pcHead;
5107 //fprintf(stderr, "multiple labels\n");
5108 //pc->print(stderr,pc);
5113 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5114 //fprintf(stderr,"Used by:\n");
5115 //pcd->print(stderr,pcd);
5117 exchangeLabels(PCL(pbr->pc),pcd);
5126 for(pc = pb->pcHead; pc; pc = pc->next) {
5128 if(isPCL(pc)) // Label pcode
5130 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
5131 pcl = PCL(PCI(pc)->label->pc);
5134 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5136 /* This pCode is a label, so search the pBlock to see if anyone
5139 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5140 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5141 /* Couldn't find an instruction that refers to this label
5142 * So, unlink the pCode label from it's pCode chain
5143 * and destroy the label */
5144 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5146 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5147 if(pc->type == PC_LABEL) {
5149 pCodeLabelDestruct(pc);
5151 unlinkpCodeFromBranch(pc, PCODE(pcl));
5152 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5163 /*-----------------------------------------------------------------*/
5164 /* pBlockMergeLabels - remove the pCode labels from the pCode */
5165 /* chain and put them into pBranches that are */
5166 /* associated with the appropriate pCode */
5168 /*-----------------------------------------------------------------*/
5169 void pBlockMergeLabels(pBlock *pb)
5172 pCode *pc, *pcnext=NULL;
5177 /* First, Try to remove any unused labels */
5178 //pBlockRemoveUnusedLabels(pb);
5180 /* Now loop through the pBlock and merge the labels with the opcodes */
5183 // for(pc = pb->pcHead; pc; pc = pc->next) {
5186 pCode *pcn = pc->next;
5188 if(pc->type == PC_LABEL) {
5190 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5191 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5192 if((pcnext = findNextInstruction(pc) )) {
5194 // Unlink the pCode label from it's pCode chain
5197 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5198 // And link it into the instruction's pBranch labels. (Note, since
5199 // it's possible to have multiple labels associated with one instruction
5200 // we must provide a means to accomodate the additional labels. Thus
5201 // the labels are placed into the singly-linked list "label" as
5202 // opposed to being a single member of the pCodeInstruction.)
5204 //_ALLOC(pbr,sizeof(pBranch));
5205 pbr = Safe_calloc(1,sizeof(pBranch));
5209 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5212 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5214 } else if(pc->type == PC_CSOURCE) {
5216 /* merge the source line symbolic info into the next instruction */
5217 if((pcnext = findNextInstruction(pc) )) {
5219 // Unlink the pCode label from it's pCode chain
5221 PCI(pcnext)->cline = PCCS(pc);
5222 //fprintf(stderr, "merging CSRC\n");
5223 //genericPrint(stderr,pcnext);
5229 pBlockRemoveUnusedLabels(pb);
5233 /*-----------------------------------------------------------------*/
5234 /*-----------------------------------------------------------------*/
5235 int OptimizepCode(char dbName)
5237 #define MAX_PASSES 4
5246 DFPRINTF((stderr," Optimizing pCode\n"));
5250 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5251 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5252 matches += OptimizepBlock(pb);
5255 while(matches && ++passes < MAX_PASSES);
5260 /*-----------------------------------------------------------------*/
5261 /* popCopyGPR2Bit - copy a pcode operator */
5262 /*-----------------------------------------------------------------*/
5264 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5268 pcop = newpCodeOpBit(pc->name, bitval, 0);
5270 if( !( (pcop->type == PO_LABEL) ||
5271 (pcop->type == PO_LITERAL) ||
5272 (pcop->type == PO_STR) ))
5273 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5279 /*-----------------------------------------------------------------*/
5280 /*-----------------------------------------------------------------*/
5281 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5284 int firstBank = 'U';
5289 for (pc=pb->pcHead; pc; pc=pc->next) {
5291 firstBank = PCFL(pc)->firstBank;
5295 if (firstBank != 'U') {
5296 /* This block has already been done */
5297 if (firstBank != cur_bank) {
5298 /* This block has started with a different bank - must adjust it */
5299 if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5302 regs *reg = getRegFromInstruction(pc);
5304 DoBankSelect(pc,cur_bank);
5314 /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5317 for (pc=pb->pcHead; pc; pc=pc->next) {
5319 PCFL(pc)->firstBank = cur_bank;
5322 cur_bank = DoBankSelect(pc,cur_bank);
5325 /* Trace through branches and set the bank selection as required. */
5328 for (pc=pb->pcHead; pc; pc=pc->next) {
5330 PCFL(pc)->firstBank = cur_bank;
5334 if (PCI(pc)->op == POC_GOTO) {
5335 int lastRegIdx = LastRegIdx;
5337 /* Trace through branch */
5338 pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5341 regs *reg = getRegFromInstruction(pcl);
5343 int bankUnknown = -1;
5344 if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5346 if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5352 LastRegIdx = lastRegIdx;
5354 /* Keep track out current bank */
5355 regs *reg = getRegFromInstruction(pc);
5357 IsBankChange(pc,reg,&cur_bank);
5364 /*-----------------------------------------------------------------*/
5365 /*-----------------------------------------------------------------*/
5366 void pBlockDestruct(pBlock *pb)
5377 /*-----------------------------------------------------------------*/
5378 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5379 /* name dbName and combine them */
5380 /* into one block */
5381 /*-----------------------------------------------------------------*/
5382 void mergepBlocks(char dbName)
5385 pBlock *pb, *pbmerged = NULL,*pbn;
5387 pb = the_pFile->pbHead;
5389 //fprintf(stderr," merging blocks named %c\n",dbName);
5393 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5394 if( getpBlock_dbName(pb) == dbName) {
5396 //fprintf(stderr," merged block %c\n",dbName);
5401 addpCode2pBlock(pbmerged, pb->pcHead);
5402 /* addpCode2pBlock doesn't handle the tail: */
5403 pbmerged->pcTail = pb->pcTail;
5405 pb->prev->next = pbn;
5407 pbn->prev = pb->prev;
5412 //printpBlock(stderr, pbmerged);
5419 /*-----------------------------------------------------------------*/
5420 /* AnalyzeFlow - Examine the flow of the code and optimize */
5422 /* level 0 == minimal optimization */
5423 /* optimize registers that are used only by two instructions */
5424 /* level 1 == maximal optimization */
5425 /* optimize by looking at pairs of instructions that use the */
5427 /*-----------------------------------------------------------------*/
5429 void AnalyzeFlow(int level)
5431 static int times_called=0;
5439 /* if this is not the first time this function has been called,
5440 then clean up old flow information */
5441 if(times_called++) {
5442 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5445 RegsUnMapLiveRanges();
5451 /* Phase 2 - Flow Analysis - Register Banking
5453 * In this phase, the individual flow blocks are examined
5454 * and register banking is fixed.
5457 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5458 //FixRegisterBanking(pb);
5460 /* Phase 2 - Flow Analysis
5462 * In this phase, the pCode is partition into pCodeFlow
5463 * blocks. The flow blocks mark the points where a continuous
5464 * stream of instructions changes flow (e.g. because of
5465 * a call or goto or whatever).
5468 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5472 /* Phase 2 - Flow Analysis - linking flow blocks
5474 * In this phase, the individual flow blocks are examined
5475 * to determine their order of excution.
5478 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5481 /* Phase 3 - Flow Analysis - Flow Tree
5483 * In this phase, the individual flow blocks are examined
5484 * to determine their order of excution.
5487 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5491 /* Phase x - Flow Analysis - Used Banks
5493 * In this phase, the individual flow blocks are examined
5494 * to determine the Register Banks they use
5497 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5501 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5502 pCodeRegMapLiveRanges(pb);
5504 RemoveUnusedRegisters();
5506 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5507 pCodeRegOptimizeRegUsage(level);
5513 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5518 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5520 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5521 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5522 pcflow = pcflow->next) {
5524 FillFlow(PCFL(pcflow));
5529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5531 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5532 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5533 pcflow = pcflow->next) {
5535 FlowStats(PCFL(pcflow));
5541 /*-----------------------------------------------------------------*/
5542 /* AnalyzeBanking - Called after the memory addresses have been */
5543 /* assigned to the registers. */
5545 /*-----------------------------------------------------------------*/
5547 void AnalyzeBanking(void)
5551 if(!picIsInitialized()) {
5552 setDefMaxRam(); // Max RAM has not been included, so use default setting
5555 /* Phase x - Flow Analysis - Used Banks
5557 * In this phase, the individual flow blocks are examined
5558 * to determine the Register Banks they use
5564 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5565 // BanksUsedFlow(pb);
5566 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5567 FixRegisterBanking(pb,-1); // cur_bank is unknown
5571 /*-----------------------------------------------------------------*/
5572 /*-----------------------------------------------------------------*/
5573 DEFSETFUNC (resetrIdx)
5575 regs *r = (regs *)item;
5583 /*-----------------------------------------------------------------*/
5584 /* InitRegReuse - Initialises variables for code analyzer */
5585 /*-----------------------------------------------------------------*/
5587 void InitReuseReg(void)
5589 /* Find end of statically allocated variables for start idx */
5590 unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5592 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5593 if (r->type != REG_SFR) {
5594 maxIdx += r->size; /* Increment for all statically allocated variables */
5598 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5601 /*-----------------------------------------------------------------*/
5602 /*-----------------------------------------------------------------*/
5603 static unsigned register_reassign(pBlock *pb, unsigned idx)
5607 /* check recursion */
5608 pc = setFirstItem(pb->function_entries);
5614 DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5616 if (pb->tregisters) {
5618 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5619 if (r->type == REG_GPR) {
5621 if (r->rIdx < (int)idx) {
5624 if (peakIdx < idx) peakIdx = idx;
5625 sprintf(s,"r0x%02X", r->rIdx);
5626 DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5628 r->name = Safe_strdup(s);
5634 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5636 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5637 char *dest = get_op_from_instruction(PCI(pc));
5639 pCode *pcn = findFunction(dest);
5641 register_reassign(pcn->pb,idx);
5650 /*------------------------------------------------------------------*/
5651 /* ReuseReg were call tree permits */
5653 /* Re-allocate the GPR for optimum reuse for a given pblock */
5654 /* eg if a function m() calls function f1() and f2(), where f1 */
5655 /* allocates a local variable vf1 and f2 allocates a local */
5656 /* variable vf2. Then providing f1 and f2 do not call each other */
5657 /* they may share the same general purpose registers for vf1 and */
5659 /* This is done by first setting the the regs rIdx to start after */
5660 /* all the global variables, then walking through the call tree */
5661 /* renaming the registers to match their new idx and incrementng */
5662 /* it as it goes. If a function has already been called it will */
5663 /* only rename the registers if it has already used up those */
5664 /* registers ie rIdx of the function's registers is lower than the */
5665 /* current rIdx. That way the register will not be reused while */
5666 /* still being used by an eariler function call. */
5668 /* Note for this to work the functions need to be declared static. */
5670 /*------------------------------------------------------------------*/
5675 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5676 /* Non static functions can be called from other modules so their registers must reassign */
5677 if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5678 register_reassign(pb,peakIdx);
5682 /*-----------------------------------------------------------------*/
5683 /* buildCallTree - look at the flow and extract all of the calls */
5685 /*-----------------------------------------------------------------*/
5687 void buildCallTree(void )
5696 /* Now build the call tree.
5697 First we examine all of the pCodes for functions.
5698 Keep in mind that the function boundaries coincide
5699 with pBlock boundaries.
5701 The algorithm goes something like this:
5702 We have two nested loops. The outer loop iterates
5703 through all of the pBlocks/functions. The inner
5704 loop iterates through all of the pCodes for
5705 a given pBlock. When we begin iterating through
5706 a pBlock, the variable pc_fstart, pCode of the start
5707 of a function, is cleared. We then search for pCodes
5708 of type PC_FUNCTION. When one is encountered, we
5709 initialize pc_fstart to this and at the same time
5710 associate a new pBranch object that signifies a
5711 branch entry. If a return is found, then this signifies
5712 a function exit point. We'll link the pCodes of these
5713 returns to the matching pc_fstart.
5715 When we're done, a doubly linked list of pBranches
5716 will exist. The head of this list is stored in
5717 `the_pFile', which is the meta structure for all
5718 of the pCode. Look at the printCallTree function
5719 on how the pBranches are linked together.
5722 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5723 pCode *pc_fstart=NULL;
5724 for(pc = pb->pcHead; pc; pc = pc->next) {
5726 pCodeFunction *pcf = PCF(pc);
5729 if(STRCASECMP(pcf->fname, "_main") == 0) {
5730 //fprintf(stderr," found main \n");
5731 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5735 pbr = Safe_calloc(1,sizeof(pBranch));
5736 pbr->pc = pc_fstart = pc;
5739 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5741 // Here's a better way of doing the same:
5742 addSet(&pb->function_entries, pc);
5745 // Found an exit point in a function, e.g. return
5746 // (Note, there may be more than one return per function)
5748 pBranchLink(PCF(pc_fstart), pcf);
5750 addSet(&pb->function_exits, pc);
5752 } else if(isCALL(pc)) {
5753 addSet(&pb->function_calls,pc);
5759 /*-----------------------------------------------------------------*/
5760 /* AnalyzepCode - parse the pCode that has been generated and form */
5761 /* all of the logical connections. */
5763 /* Essentially what's done here is that the pCode flow is */
5765 /*-----------------------------------------------------------------*/
5767 void AnalyzepCode(char dbName)
5778 /* Phase 1 - Register allocation and peep hole optimization
5780 * The first part of the analysis is to determine the registers
5781 * that are used in the pCode. Once that is done, the peep rules
5782 * are applied to the code. We continue to loop until no more
5783 * peep rule optimizations are found (or until we exceed the
5784 * MAX_PASSES threshold).
5786 * When done, the required registers will be determined.
5792 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5794 /* First, merge the labels with the instructions */
5795 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5796 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5798 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5799 pBlockMergeLabels(pb);
5802 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5806 changes = OptimizepCode(dbName);
5808 } while(changes && (i++ < MAX_PASSES));
5813 /*-----------------------------------------------------------------*/
5814 /* ispCodeFunction - returns true if *pc is the pCode of a */
5816 /*-----------------------------------------------------------------*/
5817 bool ispCodeFunction(pCode *pc)
5820 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5826 /*-----------------------------------------------------------------*/
5827 /* findFunction - Search for a function by name (given the name) */
5828 /* in the set of all functions that are in a pBlock */
5829 /* (note - I expect this to change because I'm planning to limit */
5830 /* pBlock's to just one function declaration */
5831 /*-----------------------------------------------------------------*/
5832 pCode *findFunction(char *fname)
5839 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5841 pc = setFirstItem(pb->function_entries);
5844 if((pc->type == PC_FUNCTION) &&
5846 (strcmp(fname, PCF(pc)->fname)==0))
5849 pc = setNextItem(pb->function_entries);
5857 void MarkUsedRegisters(set *regset)
5862 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5863 r2 = pic14_regWithIdx(r1->rIdx);
5871 void pBlockStats(FILE *of, pBlock *pb)
5877 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5879 // for now just print the first element of each set
5880 pc = setFirstItem(pb->function_entries);
5882 fprintf(of,";entry: ");
5885 pc = setFirstItem(pb->function_exits);
5887 fprintf(of,";has an exit\n");
5891 pc = setFirstItem(pb->function_calls);
5893 fprintf(of,";functions called:\n");
5896 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5897 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5899 pc = setNextItem(pb->function_calls);
5903 r = setFirstItem(pb->tregisters);
5905 int n = elementsInSet(pb->tregisters);
5907 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5910 fprintf(of,"; %s\n",r->name);
5911 r = setNextItem(pb->tregisters);
5916 /*-----------------------------------------------------------------*/
5917 /*-----------------------------------------------------------------*/
5919 static void sequencepCode(void)
5925 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5927 pb->seq = GpCodeSequenceNumber+1;
5929 for( pc = pb->pcHead; pc; pc = pc->next)
5930 pc->seq = ++GpCodeSequenceNumber;
5936 /*-----------------------------------------------------------------*/
5937 /*-----------------------------------------------------------------*/
5939 set *register_usage(pBlock *pb)
5942 set *registers=NULL;
5943 set *registersInCallPath = NULL;
5945 / * check recursion * /
5947 pc = setFirstItem(pb->function_entries);
5954 if(pc->type != PC_FUNCTION)
5955 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5957 pc = setFirstItem(pb->function_calls);
5958 for( ; pc; pc = setNextItem(pb->function_calls)) {
5960 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5961 char *dest = get_op_from_instruction(PCI(pc));
5963 pcn = findFunction(dest);
5965 registersInCallPath = register_usage(pcn->pb);
5967 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5972 pBlockStats(stderr,pb); // debug
5975 // Mark the registers in this block as used.
5977 MarkUsedRegisters(pb->tregisters);
5978 if(registersInCallPath) {
5979 / * registers were used in the functions this pBlock has called * /
5980 / * so now, we need to see if these collide with the ones we are * /
5983 regs *r1,*r2, *newreg;
5985 DFPRINTF((stderr,"comparing registers\n"));
5987 r1 = setFirstItem(registersInCallPath);
5989 if (r1->type != REG_STK) {
5990 r2 = setFirstItem(pb->tregisters);
5992 while(r2 && (r2->type != REG_STK)) {
5994 if(r2->rIdx == r1->rIdx) {
5995 newreg = pic14_findFreeReg(REG_GPR);
5999 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6003 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6004 r1->rIdx, newreg->rIdx));
6005 r2->rIdx = newreg->rIdx;
6007 r2->name = Safe_strdup(newreg->name);
6011 newreg->wasUsed = 1;
6013 r2 = setNextItem(pb->tregisters);
6017 r1 = setNextItem(registersInCallPath);
6020 / * Collisions have been resolved. Now free the registers in the call path * /
6021 r1 = setFirstItem(registersInCallPath);
6023 newreg = pic14_regWithIdx(r1->rIdx);
6024 if (newreg) newreg->isFree = 1;
6025 r1 = setNextItem(registersInCallPath);
6029 // MarkUsedRegisters(pb->registers);
6031 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6034 DFPRINTF((stderr,"returning regs\n"));
6036 DFPRINTF((stderr,"not returning regs\n"));
6038 DFPRINTF((stderr,"pBlock after register optim.\n"));
6039 pBlockStats(stderr,pb); // debug
6046 /*-----------------------------------------------------------------*/
6047 /* printCallTree - writes the call tree to a file */
6049 /*-----------------------------------------------------------------*/
6050 void pct2(FILE *of,pBlock *pb,int indent)
6054 // set *registersInCallPath = NULL;
6060 return; //recursion ?
6062 pc = setFirstItem(pb->function_entries);
6069 for(i=0;i<indent;i++) // Indentation
6072 if(pc->type == PC_FUNCTION)
6073 fprintf(of,"%s\n",PCF(pc)->fname);
6078 pc = setFirstItem(pb->function_calls);
6079 for( ; pc; pc = setNextItem(pb->function_calls)) {
6081 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6082 char *dest = get_op_from_instruction(PCI(pc));
6084 pcn = findFunction(dest);
6086 pct2(of,pcn->pb,indent+1);
6088 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6096 /*-----------------------------------------------------------------*/
6097 /* printCallTree - writes the call tree to a file */
6099 /*-----------------------------------------------------------------*/
6101 void printCallTree(FILE *of)
6113 fprintf(of, "\npBlock statistics\n");
6114 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6119 fprintf(of,"Call Tree\n");
6120 pbr = the_pFile->functions;
6124 if(!ispCodeFunction(pc))
6125 fprintf(of,"bug in call tree");
6128 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6130 while(pc->next && !ispCodeFunction(pc->next)) {
6132 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6133 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
6141 fprintf(of,"\n**************\n\na better call tree\n");
6142 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6147 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6148 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6154 /*-----------------------------------------------------------------*/
6156 /*-----------------------------------------------------------------*/
6158 void InlineFunction(pBlock *pb)
6166 pc = setFirstItem(pb->function_calls);
6168 for( ; pc; pc = setNextItem(pb->function_calls)) {
6171 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6172 pCode *pcp = pc->prev;
6178 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 */
6180 InlineFunction(pcn->pb);
6183 At this point, *pc points to a CALL mnemonic, and
6184 *pcn points to the function that is being called.
6186 To in-line this call, we need to remove the CALL
6187 and RETURN(s), and link the function pCode in with
6194 /* Check if previous instruction was a bit skip */
6195 if (isPCI_BITSKIP(pcp)) {
6197 /* Invert skip instruction and add a goto */
6198 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6200 if(isPCL(pc_call->next)) { // Label pcode
6201 pcl = PCL(pc_call->next);
6202 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6203 pcl = PCL(PCI(pc_call->next)->label->pc);
6205 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6206 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6208 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6211 /* remove callee pBlock from the pBlock linked list */
6212 removepBlock(pcn->pb);
6220 /* Remove the Function pCode */
6221 pct = findNextInstruction(pcn->next);
6223 /* Link the function with the callee */
6224 if (pcp) pcp->next = pcn->next;
6225 pcn->next->prev = pcp;
6227 /* Convert the function name into a label */
6229 pbr = Safe_calloc(1,sizeof(pBranch));
6230 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6232 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6233 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6235 /* turn all of the return's except the last into goto's */
6236 /* check case for 2 instruction pBlocks */
6237 pce = findNextInstruction(pcn->next);
6239 pCode *pce_next = findNextInstruction(pce->next);
6241 if(pce_next == NULL) {
6242 /* found the last return */
6243 pCode *pc_call_next = findNextInstruction(pc_call->next);
6245 //fprintf(stderr,"found last return\n");
6246 //pce->print(stderr,pce);
6247 pce->prev->next = pc_call->next;
6248 pc_call->next->prev = pce->prev;
6249 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6258 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6264 /*-----------------------------------------------------------------*/
6266 /*-----------------------------------------------------------------*/
6268 void InlinepCode(void)
6277 if(!functionInlining)
6280 /* Loop through all of the function definitions and count the
6281 * number of times each one is called */
6282 //fprintf(stderr,"inlining %d\n",__LINE__);
6284 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6286 pc = setFirstItem(pb->function_calls);
6288 for( ; pc; pc = setNextItem(pb->function_calls)) {
6291 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6292 if(pcn && isPCF(pcn)) {
6293 PCF(pcn)->ncalled++;
6296 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6301 //fprintf(stderr,"inlining %d\n",__LINE__);
6303 /* Now, Loop through the function definitions again, but this
6304 * time inline those functions that have only been called once. */
6306 InlineFunction(the_pFile->pbHead);
6307 //fprintf(stderr,"inlining %d\n",__LINE__);
6309 for(pb = the_pFile->pbHead; pb; pb = pb->next)