1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb);
36 /****************************************************************/
37 /****************************************************************/
39 peepCommand peepCommands[] = {
41 {NOTBITSKIP, "_NOTBITSKIP_"},
42 {BITSKIP, "_BITSKIP_"},
43 {INVERTBITSKIP, "_INVERTBITSKIP_"},
50 // Eventually this will go into device dependent files:
51 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
52 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
53 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
62 static int mnemonics_initialized = 0;
64 static hTab *pic14MnemonicsHash = NULL;
65 static hTab *pic14pCodePeepCommandsHash = NULL;
68 pFile *the_pFile = NULL;
69 static pBlock *pb_dead_pcodes = NULL;
71 /* Hardcoded flags to change the behavior of the PIC port */
72 static int functionInlining = 1; /* inline functions if nonzero */
73 int debug_verbose = 0; /* Set true to inundate .asm file */
75 // static int GpCodeSequenceNumber = 1;
78 /* statistics (code size estimation) */
79 static unsigned int pcode_insns = 0;
80 static unsigned int pcode_doubles = 0;
83 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
84 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
86 extern void RemoveUnusedRegisters(void);
87 extern void RegsUnMapLiveRanges(void);
88 extern void BuildFlowTree(pBlock *pb);
89 extern void pCodeRegOptimizeRegUsage(int level);
90 extern int picIsInitialized(void);
91 extern const char *pCodeOpType(pCodeOp *pcop);
93 /****************************************************************/
94 /* Forward declarations */
95 /****************************************************************/
97 void unlinkpCode(pCode *pc);
99 static void genericAnalyze(pCode *pc);
100 static void AnalyzeGOTO(pCode *pc);
101 static void AnalyzeSKIP(pCode *pc);
102 static void AnalyzeRETURN(pCode *pc);
105 static void genericDestruct(pCode *pc);
106 static void genericPrint(FILE *of,pCode *pc);
108 static void pCodePrintLabel(FILE *of, pCode *pc);
109 static void pCodePrintFunction(FILE *of, pCode *pc);
110 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
111 static char *get_op_from_instruction( pCodeInstruction *pcc);
112 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
113 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
114 int pCodePeepMatchRule(pCode *pc);
115 void pBlockStats(FILE *of, pBlock *pb);
116 pBlock *newpBlock(void);
117 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
118 void pCodeRegMapLiveRanges(pBlock *pb);
120 pBranch * pBranchAppend(pBranch *h, pBranch *n);
123 /****************************************************************/
124 /* PIC Instructions */
125 /****************************************************************/
127 pCodeInstruction pciADDWF = {
128 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
141 1,0, // dest, bit instruction
143 0, // literal operand
145 (PCC_W | PCC_REGISTER), // inCond
146 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
149 pCodeInstruction pciADDFW = {
150 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
163 0,0, // dest, bit instruction
165 0, // literal operand
167 (PCC_W | PCC_REGISTER), // inCond
168 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
171 pCodeInstruction pciADDLW = {
172 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
185 0,0, // dest, bit instruction
187 1, // literal operand
189 (PCC_W | PCC_LITERAL), // inCond
190 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
193 pCodeInstruction pciANDLW = {
194 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
207 0,0, // dest, bit instruction
209 1, // literal operand
211 (PCC_W | PCC_LITERAL), // inCond
212 (PCC_W | PCC_Z) // outCond
215 pCodeInstruction pciANDWF = {
216 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
229 1,0, // dest, bit instruction
231 0, // literal operand
233 (PCC_W | PCC_REGISTER), // inCond
234 (PCC_REGISTER | PCC_Z) // outCond
237 pCodeInstruction pciANDFW = {
238 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
251 0,0, // dest, bit instruction
253 0, // literal operand
255 (PCC_W | PCC_REGISTER), // inCond
256 (PCC_W | PCC_Z) // outCond
259 pCodeInstruction pciBCF = {
260 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
273 1,1, // dest, bit instruction
275 0, // literal operand
277 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
278 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
281 pCodeInstruction pciBSF = {
282 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
295 1,1, // dest, bit instruction
297 0, // literal operand
299 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
300 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
303 pCodeInstruction pciBTFSC = {
304 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
317 0,1, // dest, bit instruction
319 0, // literal operand
321 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
325 pCodeInstruction pciBTFSS = {
326 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
339 0,1, // dest, bit instruction
341 0, // literal operand
343 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
347 pCodeInstruction pciCALL = {
348 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
361 0,0, // dest, bit instruction
363 0, // literal operand
365 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
366 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
369 pCodeInstruction pciCOMF = {
370 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
383 1,0, // dest, bit instruction
385 0, // literal operand
387 PCC_REGISTER, // inCond
388 PCC_REGISTER | PCC_Z // outCond
391 pCodeInstruction pciCOMFW = {
392 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
405 0,0, // dest, bit instruction
407 0, // literal operand
409 PCC_REGISTER, // inCond
410 PCC_W | PCC_Z // outCond
413 pCodeInstruction pciCLRF = {
414 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
427 0,0, // dest, bit instruction
429 0, // literal operand
432 PCC_REGISTER | PCC_Z // outCond
435 pCodeInstruction pciCLRW = {
436 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
449 0,0, // dest, bit instruction
451 0, // literal operand
454 PCC_W | PCC_Z // outCond
457 pCodeInstruction pciCLRWDT = {
458 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
471 0,0, // dest, bit instruction
473 0, // literal operand
479 pCodeInstruction pciDECF = {
480 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
493 1,0, // dest, bit instruction
495 0, // literal operand
497 PCC_REGISTER, // inCond
498 PCC_REGISTER | PCC_Z // outCond
501 pCodeInstruction pciDECFW = {
502 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
515 0,0, // dest, bit instruction
517 0, // literal operand
519 PCC_REGISTER, // inCond
520 PCC_W | PCC_Z // outCond
523 pCodeInstruction pciDECFSZ = {
524 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
537 1,0, // dest, bit instruction
539 0, // literal operand
540 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
541 PCC_REGISTER, // inCond
542 PCC_REGISTER | PCC_Z // outCond
545 pCodeInstruction pciDECFSZW = {
546 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
559 0,0, // dest, bit instruction
561 0, // literal operand
562 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
563 PCC_REGISTER, // inCond
564 PCC_W | PCC_Z // outCond
567 pCodeInstruction pciGOTO = {
568 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
581 0,0, // dest, bit instruction
583 0, // literal operand
589 pCodeInstruction pciINCF = {
590 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
603 1,0, // dest, bit instruction
605 0, // literal operand
607 PCC_REGISTER, // inCond
608 PCC_REGISTER | PCC_Z // outCond
611 pCodeInstruction pciINCFW = {
612 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
625 0,0, // dest, bit instruction
627 0, // literal operand
629 PCC_REGISTER, // inCond
630 PCC_W | PCC_Z // outCond
633 pCodeInstruction pciINCFSZ = {
634 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
647 1,0, // dest, bit instruction
649 0, // literal operand
650 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
651 PCC_REGISTER, // inCond
652 PCC_REGISTER | PCC_Z // outCond
655 pCodeInstruction pciINCFSZW = {
656 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
669 0,0, // dest, bit instruction
671 0, // literal operand
672 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
673 PCC_REGISTER, // inCond
674 PCC_W | PCC_Z // outCond
677 pCodeInstruction pciIORWF = {
678 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
691 1,0, // dest, bit instruction
693 0, // literal operand
695 (PCC_W | PCC_REGISTER), // inCond
696 (PCC_REGISTER | PCC_Z) // outCond
699 pCodeInstruction pciIORFW = {
700 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
713 0,0, // dest, bit instruction
715 0, // literal operand
717 (PCC_W | PCC_REGISTER), // inCond
718 (PCC_W | PCC_Z) // outCond
721 pCodeInstruction pciIORLW = {
722 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
735 0,0, // dest, bit instruction
737 1, // literal operand
739 (PCC_W | PCC_LITERAL), // inCond
740 (PCC_W | PCC_Z) // outCond
743 pCodeInstruction pciMOVF = {
744 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
757 1,0, // dest, bit instruction
759 0, // literal operand
761 PCC_REGISTER, // inCond
765 pCodeInstruction pciMOVFW = {
766 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
779 0,0, // dest, bit instruction
781 0, // literal operand
783 PCC_REGISTER, // inCond
784 (PCC_W | PCC_Z) // outCond
787 pCodeInstruction pciMOVWF = {
788 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
801 0,0, // dest, bit instruction
803 0, // literal operand
806 PCC_REGISTER // outCond
809 pCodeInstruction pciMOVLW = {
810 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
822 0,0, // dest, bit instruction
824 1, // literal operand
826 (PCC_NONE | PCC_LITERAL), // inCond
830 pCodeInstruction pciNOP = {
831 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
843 0,0, // dest, bit instruction
845 0, // literal operand
851 pCodeInstruction pciRETFIE = {
852 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
870 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
873 pCodeInstruction pciRETLW = {
874 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
887 0,0, // dest, bit instruction
889 1, // literal operand
891 PCC_LITERAL, // inCond
892 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
895 pCodeInstruction pciRETURN = {
896 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
909 0,0, // dest, bit instruction
911 0, // literal operand
913 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
914 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
917 pCodeInstruction pciRLF = {
918 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
931 1,0, // dest, bit instruction
933 0, // literal operand
935 (PCC_C | PCC_REGISTER), // inCond
936 (PCC_REGISTER | PCC_C ) // outCond
939 pCodeInstruction pciRLFW = {
940 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
953 0,0, // dest, bit instruction
955 0, // literal operand
957 (PCC_C | PCC_REGISTER), // inCond
958 (PCC_W | PCC_C) // outCond
961 pCodeInstruction pciRRF = {
962 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
975 1,0, // dest, bit instruction
977 0, // literal operand
979 (PCC_C | PCC_REGISTER), // inCond
980 (PCC_REGISTER | PCC_C) // outCond
983 pCodeInstruction pciRRFW = {
984 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
997 0,0, // dest, bit instruction
999 0, // literal operand
1001 (PCC_C | PCC_REGISTER), // inCond
1002 (PCC_W | PCC_C) // outCond
1005 pCodeInstruction pciSUBWF = {
1006 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1012 NULL, // from branch
1019 1,0, // dest, bit instruction
1020 0,0, // branch, skip
1021 0, // literal operand
1023 (PCC_W | PCC_REGISTER), // inCond
1024 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1027 pCodeInstruction pciSUBFW = {
1028 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1034 NULL, // from branch
1041 0,0, // dest, bit instruction
1042 0,0, // branch, skip
1043 0, // literal operand
1045 (PCC_W | PCC_REGISTER), // inCond
1046 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1049 pCodeInstruction pciSUBLW = {
1050 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1056 NULL, // from branch
1063 0,0, // dest, bit instruction
1064 0,0, // branch, skip
1065 1, // literal operand
1067 (PCC_W | PCC_LITERAL), // inCond
1068 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1071 pCodeInstruction pciSWAPF = {
1072 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1078 NULL, // from branch
1085 1,0, // dest, bit instruction
1086 0,0, // branch, skip
1087 0, // literal operand
1089 (PCC_REGISTER), // inCond
1090 (PCC_REGISTER) // outCond
1093 pCodeInstruction pciSWAPFW = {
1094 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1100 NULL, // from branch
1107 0,0, // dest, bit instruction
1108 0,0, // branch, skip
1109 0, // literal operand
1111 (PCC_REGISTER), // inCond
1115 pCodeInstruction pciTRIS = {
1116 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1122 NULL, // from branch
1129 0,0, // dest, bit instruction
1130 0,0, // branch, skip
1131 0, // literal operand
1133 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1134 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1137 pCodeInstruction pciXORWF = {
1138 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1144 NULL, // from branch
1151 1,0, // dest, bit instruction
1152 0,0, // branch, skip
1153 0, // literal operand
1155 (PCC_W | PCC_REGISTER), // inCond
1156 (PCC_REGISTER | PCC_Z) // outCond
1159 pCodeInstruction pciXORFW = {
1160 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1166 NULL, // from branch
1173 0,0, // dest, bit instruction
1174 0,0, // branch, skip
1175 0, // literal operand
1177 (PCC_W | PCC_REGISTER), // inCond
1178 (PCC_W | PCC_Z) // outCond
1181 pCodeInstruction pciXORLW = {
1182 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1188 NULL, // from branch
1195 0,0, // dest, bit instruction
1196 0,0, // branch, skip
1197 1, // literal operand
1199 (PCC_W | PCC_LITERAL), // inCond
1200 (PCC_W | PCC_Z) // outCond
1204 pCodeInstruction pciBANKSEL = {
1205 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1211 NULL, // from branch
1218 0,0, // dest, bit instruction
1219 0,0, // branch, skip
1220 0, // literal operand
1226 pCodeInstruction pciPAGESEL = {
1227 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1233 NULL, // from branch
1240 0,0, // dest, bit instruction
1241 0,0, // branch, skip
1242 0, // literal operand
1248 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1251 /*-----------------------------------------------------------------*/
1252 /* return a unique ID number to assist pCodes debuging */
1253 /*-----------------------------------------------------------------*/
1254 unsigned PCodeID(void) {
1255 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1257 static unsigned int stop;
1258 if (pcodeId == 1448)
1259 stop++; // Place break point here
1264 #ifdef HAVE_VSNPRINTF
1265 // Alas, vsnprintf is not ANSI standard, and does not exist
1266 // on Solaris (and probably other non-Gnu flavored Unixes).
1268 /*-----------------------------------------------------------------*/
1269 /* SAFE_snprintf - like snprintf except the string pointer is */
1270 /* after the string has been printed to. This is */
1271 /* useful for printing to string as though if it */
1272 /* were a stream. */
1273 /*-----------------------------------------------------------------*/
1274 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1282 va_start(val, format);
1284 vsnprintf(*str, *size, format, val);
1289 if((size_t)len > *size) {
1290 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1291 fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1299 #else // HAVE_VSNPRINTF
1301 // This version is *not* safe, despite the name.
1303 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
1307 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1312 va_start(val, format);
1314 vsprintf(buffer, format, val);
1317 len = strlen(buffer);
1319 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1320 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1323 strcpy(*str, buffer);
1329 #endif // HAVE_VSNPRINTF
1332 extern void initStack(int base_address, int size, int shared);
1333 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1334 extern regs *allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias);
1335 extern PIC_device *init_pic(char *);
1337 void pCodeInitRegisters(void)
1339 static int initialized=0;
1340 int shareBankAddress, stkSize, haveShared;
1347 pic = init_pic(port->processor);
1348 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1349 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1350 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1351 * (used for interrupts) to fit into the shared portion of the
1353 stkSize = stkSize - 3;
1354 assert(stkSize >= 0);
1355 initStack(shareBankAddress, stkSize, haveShared);
1357 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1358 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1359 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1360 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1361 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1362 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1363 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1365 pc_status.rIdx = IDX_STATUS;
1366 pc_fsr.rIdx = IDX_FSR;
1367 pc_indf.rIdx = IDX_INDF;
1368 pc_intcon.rIdx = IDX_INTCON;
1369 pc_pcl.rIdx = IDX_PCL;
1370 pc_pclath.rIdx = IDX_PCLATH;
1372 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1373 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1374 /* Interrupt storage for status register. */
1375 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1376 /* Interrupt storage for pclath register. */
1377 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1379 pc_wsave.rIdx = pc_wsave.r->rIdx;
1380 pc_ssave.rIdx = pc_ssave.r->rIdx;
1381 pc_psave.rIdx = pc_psave.r->rIdx;
1383 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1384 pc_wsave.r->address = shareBankAddress-stkSize;
1385 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1386 pc_ssave.r->address = shareBankAddress-stkSize-1;
1387 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1388 pc_psave.r->address = shareBankAddress-stkSize-2;
1390 /* probably should put this in a separate initialization routine */
1391 pb_dead_pcodes = newpBlock();
1395 /*-----------------------------------------------------------------*/
1396 /* mnem2key - convert a pic mnemonic into a hash key */
1397 /* (BTW - this spreads the mnemonics quite well) */
1399 /*-----------------------------------------------------------------*/
1401 int mnem2key(unsigned char const *mnem)
1410 key += toupper(*mnem++) +1;
1414 return (key & 0x1f);
1418 void pic14initMnemonics(void)
1423 pCodeInstruction *pci;
1425 if(mnemonics_initialized)
1428 //FIXME - probably should NULL out the array before making the assignments
1429 //since we check the array contents below this initialization.
1431 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1432 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1433 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1434 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1435 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1436 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1437 pic14Mnemonics[POC_BCF] = &pciBCF;
1438 pic14Mnemonics[POC_BSF] = &pciBSF;
1439 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1440 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1441 pic14Mnemonics[POC_CALL] = &pciCALL;
1442 pic14Mnemonics[POC_COMF] = &pciCOMF;
1443 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1444 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1445 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1446 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1447 pic14Mnemonics[POC_DECF] = &pciDECF;
1448 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1449 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1450 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1451 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1452 pic14Mnemonics[POC_INCF] = &pciINCF;
1453 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1454 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1455 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1456 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1457 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1458 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1459 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1460 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1461 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1462 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1463 pic14Mnemonics[POC_NOP] = &pciNOP;
1464 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1465 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1466 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1467 pic14Mnemonics[POC_RLF] = &pciRLF;
1468 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1469 pic14Mnemonics[POC_RRF] = &pciRRF;
1470 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1471 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1472 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1473 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1474 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1475 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1476 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1477 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1478 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1479 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1480 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1481 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1483 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1484 if(pic14Mnemonics[i])
1485 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1486 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1489 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1490 pci = hTabNextItem(pic14MnemonicsHash, &key);
1493 mnemonics_initialized = 1;
1496 int getpCodePeepCommand(char *cmd);
1498 int getpCode(char *mnem,unsigned dest)
1501 pCodeInstruction *pci;
1502 int key = mnem2key((unsigned char *)mnem);
1504 if(!mnemonics_initialized)
1505 pic14initMnemonics();
1507 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1511 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1512 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1516 pci = hTabNextItemWK (pic14MnemonicsHash);
1523 /*-----------------------------------------------------------------*
1524 * pic14initpCodePeepCommands
1526 *-----------------------------------------------------------------*/
1527 void pic14initpCodePeepCommands(void)
1535 hTabAddItem(&pic14pCodePeepCommandsHash,
1536 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1538 } while (peepCommands[i].cmd);
1540 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1543 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1544 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1549 /*-----------------------------------------------------------------
1552 *-----------------------------------------------------------------*/
1554 int getpCodePeepCommand(char *cmd)
1558 int key = mnem2key((unsigned char *)cmd);
1561 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1564 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1565 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1569 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1576 char getpBlock_dbName(pBlock *pb)
1582 return pb->cmemmap->dbName;
1586 void pBlockConvert2ISR(pBlock *pb)
1597 /*-----------------------------------------------------------------*/
1598 /* movepBlock2Head - given the dbname of a pBlock, move all */
1599 /* instances to the front of the doubly linked */
1600 /* list of pBlocks */
1601 /*-----------------------------------------------------------------*/
1603 void movepBlock2Head(char dbName)
1610 pb = the_pFile->pbHead;
1614 if(getpBlock_dbName(pb) == dbName) {
1615 pBlock *pbn = pb->next;
1616 pb->next = the_pFile->pbHead;
1617 the_pFile->pbHead->prev = pb;
1618 the_pFile->pbHead = pb;
1621 pb->prev->next = pbn;
1623 // If the pBlock that we just moved was the last
1624 // one in the link of all of the pBlocks, then we
1625 // need to point the tail to the block just before
1626 // the one we moved.
1627 // Note: if pb->next is NULL, then pb must have
1628 // been the last pBlock in the chain.
1631 pbn->prev = pb->prev;
1633 the_pFile->pbTail = pb->prev;
1644 void copypCode(FILE *of, char dbName)
1648 if(!of || !the_pFile)
1651 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1652 if(getpBlock_dbName(pb) == dbName) {
1661 void resetpCodeStatistics (void)
1663 pcode_insns = pcode_doubles = 0;
1666 void dumppCodeStatistics (FILE *of)
1668 /* dump statistics */
1670 fprintf (of, ";\tcode size estimation:\n");
1671 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1675 void pcode_test(void)
1678 DFPRINTF((stderr,"pcode is alive!\n"));
1688 /* create the file name */
1689 strcpy(buffer,dstFileName);
1690 strcat(buffer,".p");
1692 if( !(pFile = fopen(buffer, "w" ))) {
1693 werror(E_FILE_OPEN_ERR,buffer);
1697 fprintf(pFile,"pcode dump\n\n");
1699 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1700 fprintf(pFile,"\n\tNew pBlock\n\n");
1702 fprintf(pFile,"%s",pb->cmemmap->sname);
1704 fprintf(pFile,"internal pblock");
1706 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1707 printpBlock(pFile,pb);
1711 /*-----------------------------------------------------------------*/
1712 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1713 /* ister, RegCond will return the bit being referenced. */
1715 /* fixme - why not just OR in the pcop bit field */
1716 /*-----------------------------------------------------------------*/
1718 static int RegCond(pCodeOp *pcop)
1724 if (pcop->type == PO_GPR_BIT) {
1725 char *name = pcop->name;
1727 name = PCOR(pcop)->r->name;
1728 if (strcmp(name, pc_status.pcop.name) == 0)
1730 switch(PCORB(pcop)->bit) {
1744 /*-----------------------------------------------------------------*/
1745 /* newpCode - create and return a newly initialized pCode */
1747 /* fixme - rename this */
1749 /* The purpose of this routine is to create a new Instruction */
1750 /* pCode. This is called by gen.c while the assembly code is being */
1754 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1755 /* (note that the op is analogous to but not the */
1756 /* same thing as the opcode of the instruction.) */
1757 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1760 /* a pointer to the new malloc'd pCode is returned. */
1764 /*-----------------------------------------------------------------*/
1765 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1767 pCodeInstruction *pci ;
1769 if(!mnemonics_initialized)
1770 pic14initMnemonics();
1772 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1774 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1775 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1776 pci->pc.id = PCodeID();
1779 if(pci->inCond & PCC_EXAMINE_PCOP)
1780 pci->inCond |= RegCond(pcop);
1782 if(pci->outCond & PCC_EXAMINE_PCOP)
1783 pci->outCond |= RegCond(pcop);
1785 pci->pc.prev = pci->pc.next = NULL;
1786 return (pCode *)pci;
1789 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1795 /*-----------------------------------------------------------------*/
1796 /* newpCodeWild - create a "wild" as in wild card pCode */
1798 /* Wild pcodes are used during the peep hole optimizer to serve */
1799 /* as place holders for any instruction. When a snippet of code is */
1800 /* compared to a peep hole rule, the wild card opcode will match */
1801 /* any instruction. However, the optional operand and label are */
1802 /* additional qualifiers that must also be matched before the */
1803 /* line (of assembly code) is declared matched. Note that the */
1804 /* operand may be wild too. */
1806 /* Note, a wild instruction is specified just like a wild var: */
1807 /* %4 ; A wild instruction, */
1808 /* See the peeph.def file for additional examples */
1810 /*-----------------------------------------------------------------*/
1812 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1817 pcw = Safe_calloc(1,sizeof(pCodeWild));
1819 pcw->pci.pc.type = PC_WILD;
1820 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1821 pcw->id = PCodeID();
1822 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1823 pcw->pci.pc.pb = NULL;
1825 // pcw->pci.pc.analyze = genericAnalyze;
1826 pcw->pci.pc.destruct = genericDestruct;
1827 pcw->pci.pc.print = genericPrint;
1829 pcw->id = pCodeID; // this is the 'n' in %n
1830 pcw->operand = optional_operand;
1831 pcw->label = optional_label;
1833 pcw->mustBeBitSkipInst = 0;
1834 pcw->mustNotBeBitSkipInst = 0;
1835 pcw->invertBitSkipInst = 0;
1837 return ( (pCode *)pcw);
1841 /*-----------------------------------------------------------------*/
1842 /* newPcodeInlineP - create a new pCode from a char string */
1843 /*-----------------------------------------------------------------*/
1846 pCode *newpCodeInlineP(char *cP)
1851 pcc = Safe_calloc(1,sizeof(pCodeComment));
1853 pcc->pc.type = PC_INLINE;
1854 pcc->pc.prev = pcc->pc.next = NULL;
1855 pcc->pc.id = PCodeID();
1856 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1859 // pcc->pc.analyze = genericAnalyze;
1860 pcc->pc.destruct = genericDestruct;
1861 pcc->pc.print = genericPrint;
1864 pcc->comment = Safe_strdup(cP);
1866 pcc->comment = NULL;
1868 return ( (pCode *)pcc);
1872 /*-----------------------------------------------------------------*/
1873 /* newPcodeCharP - create a new pCode from a char string */
1874 /*-----------------------------------------------------------------*/
1876 pCode *newpCodeCharP(char *cP)
1881 pcc = Safe_calloc(1,sizeof(pCodeComment));
1883 pcc->pc.type = PC_COMMENT;
1884 pcc->pc.prev = pcc->pc.next = NULL;
1885 pcc->pc.id = PCodeID();
1886 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1889 // pcc->pc.analyze = genericAnalyze;
1890 pcc->pc.destruct = genericDestruct;
1891 pcc->pc.print = genericPrint;
1894 pcc->comment = Safe_strdup(cP);
1896 pcc->comment = NULL;
1898 return ( (pCode *)pcc);
1902 /*-----------------------------------------------------------------*/
1903 /* newpCodeFunction - */
1904 /*-----------------------------------------------------------------*/
1907 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1911 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1912 //_ALLOC(pcf,sizeof(pCodeFunction));
1914 pcf->pc.type = PC_FUNCTION;
1915 pcf->pc.prev = pcf->pc.next = NULL;
1916 pcf->pc.id = PCodeID();
1917 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1920 // pcf->pc.analyze = genericAnalyze;
1921 pcf->pc.destruct = genericDestruct;
1922 pcf->pc.print = pCodePrintFunction;
1927 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1928 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1929 strcpy(pcf->modname,mod);
1931 pcf->modname = NULL;
1934 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1935 pcf->fname = Safe_calloc(1,strlen(f)+1);
1936 strcpy(pcf->fname,f);
1940 pcf->isPublic = (unsigned)isPublic;
1942 return ( (pCode *)pcf);
1946 /*-----------------------------------------------------------------*/
1948 /*-----------------------------------------------------------------*/
1949 void destructpCodeFlow(pCode *pc)
1951 if(!pc || !isPCFL(pc))
1960 deleteSet(&PCFL(pc)->registers);
1961 deleteSet(&PCFL(pc)->from);
1962 deleteSet(&PCFL(pc)->to);
1967 pCode *newpCodeFlow(void )
1971 //_ALLOC(pcflow,sizeof(pCodeFlow));
1972 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1974 pcflow->pc.type = PC_FLOW;
1975 pcflow->pc.prev = pcflow->pc.next = NULL;
1976 pcflow->pc.pb = NULL;
1978 // pcflow->pc.analyze = genericAnalyze;
1979 pcflow->pc.destruct = destructpCodeFlow;
1980 pcflow->pc.print = genericPrint;
1982 pcflow->pc.seq = GpcFlowSeq++;
1984 pcflow->from = pcflow->to = NULL;
1986 pcflow->inCond = PCC_NONE;
1987 pcflow->outCond = PCC_NONE;
1989 pcflow->firstBank = 'U'; /* Undetermined */
1990 pcflow->lastBank = 'U'; /* Undetermined */
1992 pcflow->FromConflicts = 0;
1993 pcflow->ToConflicts = 0;
1997 pcflow->registers = newSet();
1999 return ( (pCode *)pcflow);
2003 /*-----------------------------------------------------------------*/
2004 /*-----------------------------------------------------------------*/
2005 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2007 pCodeFlowLink *pcflowLink;
2009 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2011 pcflowLink->pcflow = pcflow;
2012 pcflowLink->bank_conflict = 0;
2017 /*-----------------------------------------------------------------*/
2018 /* newpCodeCSource - create a new pCode Source Symbol */
2019 /*-----------------------------------------------------------------*/
2021 pCode *newpCodeCSource(int ln, char *f, const char *l)
2026 pccs = Safe_calloc(1,sizeof(pCodeCSource));
2028 pccs->pc.type = PC_CSOURCE;
2029 pccs->pc.prev = pccs->pc.next = NULL;
2030 pccs->pc.id = PCodeID();
2033 pccs->pc.destruct = genericDestruct;
2034 pccs->pc.print = genericPrint;
2036 pccs->line_number = ln;
2038 pccs->line = Safe_strdup(l);
2043 pccs->file_name = Safe_strdup(f);
2045 pccs->file_name = NULL;
2047 return ( (pCode *)pccs);
2051 /*******************************************************************/
2052 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2053 /* added by VR 6-Jun-2003 */
2054 /*******************************************************************/
2056 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2063 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2064 pcad->pci.pc.type = PC_ASMDIR;
2065 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2066 pcad->pci.pc.pb = NULL;
2067 pcad->pci.pc.destruct = genericDestruct;
2068 pcad->pci.pc.print = genericPrint;
2070 if(asdir && *asdir) {
2072 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2074 pcad->directive = Safe_strdup( asdir );
2077 va_start(ap, argfmt);
2079 memset(buffer, 0, sizeof(buffer));
2080 if(argfmt && *argfmt)
2081 vsprintf(buffer, argfmt, ap);
2085 while(isspace((unsigned char)*lbp))lbp++;
2088 pcad->arg = Safe_strdup( lbp );
2090 return ((pCode *)pcad);
2093 /*-----------------------------------------------------------------*/
2094 /* pCodeLabelDestruct - free memory used by a label. */
2095 /*-----------------------------------------------------------------*/
2096 static void pCodeLabelDestruct(pCode *pc)
2102 if((pc->type == PC_LABEL) && PCL(pc)->label)
2103 free(PCL(pc)->label);
2109 pCode *newpCodeLabel(char *name, int key)
2115 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2117 pcl->pc.type = PC_LABEL;
2118 pcl->pc.prev = pcl->pc.next = NULL;
2119 pcl->pc.id = PCodeID();
2120 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2123 // pcl->pc.analyze = genericAnalyze;
2124 pcl->pc.destruct = pCodeLabelDestruct;
2125 pcl->pc.print = pCodePrintLabel;
2131 sprintf(s,"_%05d_DS_",key);
2136 pcl->label = Safe_strdup(s);
2138 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2139 return ( (pCode *)pcl);
2144 /*-----------------------------------------------------------------*/
2145 /* newpBlock - create and return a pointer to a new pBlock */
2146 /*-----------------------------------------------------------------*/
2147 pBlock *newpBlock(void)
2152 PpB = Safe_calloc(1,sizeof(pBlock) );
2153 PpB->next = PpB->prev = NULL;
2155 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2156 PpB->tregisters = NULL;
2158 PpB->FlowTree = NULL;
2164 /*-----------------------------------------------------------------*/
2165 /* newpCodeChain - create a new chain of pCodes */
2166 /*-----------------------------------------------------------------*
2168 * This function will create a new pBlock and the pointer to the
2169 * pCode that is passed in will be the first pCode in the block.
2170 *-----------------------------------------------------------------*/
2173 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2176 pBlock *pB = newpBlock();
2178 pB->pcHead = pB->pcTail = pc;
2185 /*-----------------------------------------------------------------*/
2186 /* newpCodeOpLabel - Create a new label given the key */
2187 /* Note, a negative key means that the label is part of wild card */
2188 /* (and hence a wild card label) used in the pCodePeep */
2189 /* optimizations). */
2190 /*-----------------------------------------------------------------*/
2192 pCodeOp *newpCodeOpLabel(char *name, int key)
2195 static int label_key=-1;
2199 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2200 pcop->type = PO_LABEL;
2205 sprintf(s=buffer,"_%05d_DS_",key);
2207 s = name, key = label_key--;
2209 PCOLAB(pcop)->offset = 0;
2211 pcop->name = Safe_strdup(s);
2213 ((pCodeOpLabel *)pcop)->key = key;
2215 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2219 /*-----------------------------------------------------------------*/
2220 /*-----------------------------------------------------------------*/
2221 pCodeOp *newpCodeOpLit(int lit)
2227 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2228 pcop->type = PO_LITERAL;
2232 sprintf(s,"0x%02x", (unsigned char)lit);
2234 pcop->name = Safe_strdup(s);
2237 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2242 /*-----------------------------------------------------------------*/
2243 /*-----------------------------------------------------------------*/
2244 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2248 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2249 pcop->type = PO_IMMEDIATE;
2252 pcop->name = Safe_strdup(name);
2255 r = dirregWithName(name);
2259 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2260 PCOI(pcop)->rIdx = r->rIdx;
2262 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2263 PCOI(pcop)->rIdx = -1;
2265 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2270 PCOI(pcop)->index = index;
2271 PCOI(pcop)->offset = offset;
2272 PCOI(pcop)->_const = code_space;
2273 PCOI(pcop)->_function = is_func;
2278 /*-----------------------------------------------------------------*/
2279 /*-----------------------------------------------------------------*/
2280 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2286 if(!pcwb || !subtype) {
2287 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2291 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2292 pcop->type = PO_WILD;
2293 sprintf(s,"%%%d",id);
2294 pcop->name = Safe_strdup(s);
2296 PCOW(pcop)->id = id;
2297 PCOW(pcop)->pcwb = pcwb;
2298 PCOW(pcop)->subtype = subtype;
2299 PCOW(pcop)->matched = NULL;
2303 /*-----------------------------------------------------------------*/
2304 /* Find a symbol with matching name */
2305 /*-----------------------------------------------------------------*/
2306 static symbol *symFindWithName(memmap * map, const char *name)
2310 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2311 if (sym->rname && (strcmp(sym->rname,name)==0))
2317 /*-----------------------------------------------------------------*/
2318 /*-----------------------------------------------------------------*/
2319 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2324 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2325 pcop->type = PO_GPR_BIT;
2327 PCORB(pcop)->bit = ibit;
2328 PCORB(pcop)->inBitSpace = inBitSpace;
2330 if (name) r = regFindWithName(name);
2332 // Register has not been allocated - check for symbol information
2334 sym = symFindWithName(bit, name);
2335 if (!sym) sym = symFindWithName(sfrbit, name);
2336 if (!sym) sym = symFindWithName(sfr, name);
2337 if (!sym) sym = symFindWithName(reg, name);
2338 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2339 // XXX: This ignores nesting levels, but works for globals...
2340 if (!sym) sym = findSym(SymbolTab, NULL, name);
2341 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2343 r = allocNewDirReg(sym->etype,name);
2349 PCOR(pcop)->rIdx = r->rIdx;
2351 pcop->name = Safe_strdup(name);
2352 PCOR(pcop)->r = NULL;
2353 PCOR(pcop)->rIdx = 0;
2359 pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2365 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2366 pcop->name = reg->name;
2367 pcop->type = PO_GPR_BIT;
2368 PCORB(pcop)->bit = ibit;
2369 PCORB(pcop)->inBitSpace = inBitSpace;
2370 PCOR(pcop)->r = reg;
2371 PCOR(pcop)->index = 0;
2372 PCOR(pcop)->rIdx = reg->rIdx;
2377 /*-----------------------------------------------------------------*
2378 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2380 * If rIdx >=0 then a specific register from the set of registers
2381 * will be selected. If rIdx <0, then a new register will be searched
2383 *-----------------------------------------------------------------*/
2385 pCodeOp *newpCodeOpReg(int rIdx)
2389 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2394 PCOR(pcop)->rIdx = rIdx;
2395 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2397 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2400 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2404 pcop->type = PCOR(pcop)->r->pc_type;
2409 pCodeOp *newpCodeOpRegFromStr(char *name)
2413 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2414 PCOR(pcop)->r = allocRegByName(name, 1);
2415 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2416 pcop->type = PCOR(pcop)->r->pc_type;
2417 pcop->name = PCOR(pcop)->r->name;
2422 pCodeOp *newpCodeOpStr(char *name)
2426 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2427 pcop->type = PO_STR;
2428 pcop->name = Safe_strdup(name);
2430 PCOS(pcop)->isPublic = 0;
2436 /*-----------------------------------------------------------------*/
2437 /*-----------------------------------------------------------------*/
2439 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2446 pcop = newpCodeOpBit(name, -1,0);
2450 pcop = newpCodeOpLit(-1);
2454 pcop = newpCodeOpLabel(NULL,-1);
2458 pcop = newpCodeOpReg(-1);
2461 case PO_GPR_POINTER:
2462 case PO_GPR_REGISTER:
2464 pcop = newpCodeOpRegFromStr(name);
2466 pcop = newpCodeOpReg(-1);
2470 pcop = newpCodeOpStr(name);
2474 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2477 pcop->name = Safe_strdup(name);
2485 /*-----------------------------------------------------------------*/
2486 /*-----------------------------------------------------------------*/
2487 void pCodeConstString(char *name, char *value)
2492 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2497 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2501 sprintf(buffer,"; %s = %s",name,value);
2502 for (i=strlen(buffer); i--; ) {
2503 unsigned char c = buffer[i];
2504 if (c=='\r' || c=='\n') {
2505 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2507 if (c=='\r') buffer[i+1] = 'r';
2508 else if (c=='\n') buffer[i+1] = 'n';
2512 addpCode2pBlock(pb,newpCodeCharP(buffer));
2513 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2516 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2522 /*-----------------------------------------------------------------*/
2523 /*-----------------------------------------------------------------*/
2524 void pCodeReadCodeTable(void)
2528 fprintf(stderr, " %s\n",__FUNCTION__);
2530 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2534 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2535 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2536 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2537 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2539 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2540 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2541 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2542 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2547 /*-----------------------------------------------------------------*/
2548 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2549 /*-----------------------------------------------------------------*/
2550 void addpCode2pBlock(pBlock *pb, pCode *pc)
2557 /* If this is the first pcode to be added to a block that
2558 * was initialized with a NULL pcode, then go ahead and
2559 * make this pcode the head and tail */
2560 pb->pcHead = pb->pcTail = pc;
2563 pb->pcTail->next = pc;
2565 pc->prev = pb->pcTail;
2572 /*-----------------------------------------------------------------*/
2573 /* addpBlock - place a pBlock into the pFile */
2574 /*-----------------------------------------------------------------*/
2575 void addpBlock(pBlock *pb)
2577 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2580 /* First time called, we'll pass through here. */
2581 //_ALLOC(the_pFile,sizeof(pFile));
2582 the_pFile = Safe_calloc(1,sizeof(pFile));
2583 the_pFile->pbHead = the_pFile->pbTail = pb;
2584 the_pFile->functions = NULL;
2588 the_pFile->pbTail->next = pb;
2589 pb->prev = the_pFile->pbTail;
2591 the_pFile->pbTail = pb;
2594 /*-----------------------------------------------------------------*/
2595 /* removepBlock - remove a pBlock from the pFile */
2596 /*-----------------------------------------------------------------*/
2597 void removepBlock(pBlock *pb)
2605 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2607 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2610 if(pbs == the_pFile->pbHead)
2611 the_pFile->pbHead = pbs->next;
2613 if (pbs == the_pFile->pbTail)
2614 the_pFile->pbTail = pbs->prev;
2617 pbs->next->prev = pbs->prev;
2620 pbs->prev->next = pbs->next;
2627 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2631 /*-----------------------------------------------------------------*/
2632 /* printpCode - write the contents of a pCode to a file */
2633 /*-----------------------------------------------------------------*/
2634 void printpCode(FILE *of, pCode *pc)
2645 fprintf(of,"warning - unable to print pCode\n");
2648 /*-----------------------------------------------------------------*/
2649 /* printpBlock - write the contents of a pBlock to a file */
2650 /*-----------------------------------------------------------------*/
2651 void printpBlock(FILE *of, pBlock *pb)
2661 for(pc = pb->pcHead; pc; pc = pc->next) {
2666 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2676 /*-----------------------------------------------------------------*/
2678 /* pCode processing */
2682 /*-----------------------------------------------------------------*/
2684 void unlinkpCode(pCode *pc)
2690 fprintf(stderr,"Unlinking: ");
2691 printpCode(stderr, pc);
2694 pc->prev->next = pc->next;
2696 pc->next->prev = pc->prev;
2699 /* RN: I believe this should be right here, but this did not
2700 * cure the bug I was hunting... */
2701 /* must keep labels -- attach to following instruction */
2702 if (isPCI(pc) && PCI(pc)->label && pc->next)
2704 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2707 pBranchAppend (pcnext->label, PCI(pc)->label);
2711 pc->prev = pc->next = NULL;
2715 /*-----------------------------------------------------------------*/
2716 /*-----------------------------------------------------------------*/
2718 static void genericDestruct(pCode *pc)
2724 /* For instructions, tell the register (if there's one used)
2725 * that it's no longer needed */
2726 regs *reg = getRegFromInstruction(pc);
2728 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2731 /* Instead of deleting the memory used by this pCode, mark
2732 * the object as bad so that if there's a pointer to this pCode
2733 * dangling around somewhere then (hopefully) when the type is
2734 * checked we'll catch it.
2739 addpCode2pBlock(pb_dead_pcodes, pc);
2746 /*-----------------------------------------------------------------*/
2747 /* Copies the pCodeInstruction flow pointer from source pCode */
2748 /*-----------------------------------------------------------------*/
2749 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2751 pCodeFlow *pcflow = 0;
2752 for (p=pcs; p; p=p->prev) {
2754 pcflow = PCI(p)->pcflow;
2758 pcflow = (pCodeFlow*)p;
2762 PCI(pcd)->pcflow = pcflow;
2765 /*-----------------------------------------------------------------*/
2766 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2767 /* into the pCode chain containing pc1 */
2768 /*-----------------------------------------------------------------*/
2769 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2775 pc2->next = pc1->next;
2777 pc1->next->prev = pc2;
2783 /* If this is an instrution type propogate the flow */
2785 CopyFlow(PCI(pc2),pc1);
2788 /*------------------------------------------------------------------*/
2789 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2790 /* into the pCode chain containing pc1 */
2791 /*------------------------------------------------------------------*/
2792 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2798 pc2->prev = pc1->prev;
2800 pc1->prev->next = pc2;
2806 /* If this is an instrution type propogate the flow */
2808 CopyFlow(PCI(pc2),pc1);
2811 /*-----------------------------------------------------------------*/
2812 /* pCodeOpCopy - copy a pcode operator */
2813 /*-----------------------------------------------------------------*/
2814 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2816 pCodeOp *pcopnew=NULL;
2821 switch(pcop->type) {
2824 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2825 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2833 case PO_GPR_REGISTER:
2835 case PO_GPR_POINTER:
2836 case PO_SFR_REGISTER:
2840 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2841 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2842 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2843 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2847 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2848 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2849 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2853 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2854 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2860 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2861 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2862 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2866 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2867 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2868 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2872 /* Here we expand the wild card into the appropriate type: */
2873 /* By recursively calling pCodeOpCopy */
2874 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2875 if(PCOW(pcop)->matched)
2876 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2879 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2880 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2881 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2888 assert ( !"unhandled pCodeOp type copied" );
2893 pcopnew->name = Safe_strdup(pcop->name);
2895 pcopnew->name = NULL;
2900 /*-----------------------------------------------------------------*/
2901 /* popCopyReg - copy a pcode operator */
2902 /*-----------------------------------------------------------------*/
2903 pCodeOp *popCopyReg(pCodeOpReg *pc)
2907 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2908 pcor->pcop.type = pc->pcop.type;
2910 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2911 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2913 pcor->pcop.name = NULL;
2915 if (pcor->pcop.type == PO_IMMEDIATE){
2916 PCOL(pcor)->lit = PCOL(pc)->lit;
2919 pcor->rIdx = pc->rIdx;
2923 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2928 /*-----------------------------------------------------------------*/
2929 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2930 /*-----------------------------------------------------------------*/
2931 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2933 pCodeInstruction *new_pci;
2936 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2938 new_pci = PCI(newpCode(pci->op,pci->pcop));
2940 new_pci->pc.pb = pci->pc.pb;
2941 new_pci->from = pci->from;
2942 new_pci->to = pci->to;
2943 new_pci->label = pci->label;
2944 new_pci->pcflow = pci->pcflow;
2946 return PCODE(new_pci);
2949 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 void pCodeDeleteChain(pCode *f,pCode *t)
2956 DFPRINTF((stderr,"delete pCode:\n"));
2958 //f->print(stderr,f);
2959 //f->delete(f); this dumps core...
2964 /*-----------------------------------------------------------------*/
2965 /*-----------------------------------------------------------------*/
2966 void pBlockRegs(FILE *of, pBlock *pb)
2971 r = setFirstItem(pb->tregisters);
2973 r = setNextItem(pb->tregisters);
2978 /*-----------------------------------------------------------------*/
2979 /*-----------------------------------------------------------------*/
2980 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2985 int use_buffer = 1; // copy the string to the passed buffer pointer
2990 use_buffer = 0; // Don't bother copying the string to the buffer.
2994 switch(pcop->type) {
2998 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3001 //return PCOR(pcop)->r->name;
3005 if (PCOR(pcop)->r->type == REG_STK)
3006 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3008 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3011 SAFE_snprintf(&buffer,&size,"%s",r->name);
3020 if(PCOI(pcop)->_const) {
3022 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3023 switch(PCOI(pcop)->offset) {
3025 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3028 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3031 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3034 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3035 assert ( !"offset too large" );
3036 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3039 8 * PCOI(pcop)->offset );
3042 SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3044 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3045 SAFE_snprintf(&s,&size,"(%s + %d)",
3049 switch(PCOI(pcop)->offset) {
3051 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3054 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3057 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3060 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3061 assert ( !"offset too large" );
3062 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3072 //size = sizeof(buffer);
3073 if( PCOR(pcop)->instance) {
3074 SAFE_snprintf(&s,&size,"(%s + %d)",
3076 PCOR(pcop)->instance );
3077 //fprintf(stderr,"PO_DIR %s\n",buffer);
3079 SAFE_snprintf(&s,&size,"%s",pcop->name);
3085 if(PCOLAB(pcop)->offset == 1)
3086 SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3088 SAFE_snprintf(&s,&size,"%s",pcop->name);
3095 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3098 return PCOR(pcop)->r->name;
3101 /* fall through to the default case */
3105 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3113 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3114 __FILE__, __LINE__, __FUNCTION__,
3117 return "NO operand";
3121 /*-----------------------------------------------------------------*/
3122 /*-----------------------------------------------------------------*/
3123 static char *get_op_from_instruction( pCodeInstruction *pcc)
3127 return get_op(pcc->pcop,NULL,0);
3129 return ("ERROR Null: get_op_from_instruction");
3133 /*-----------------------------------------------------------------*/
3134 /*-----------------------------------------------------------------*/
3135 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3137 fprintf(of,"pcodeopprint- not implemented\n");
3140 /*-----------------------------------------------------------------*/
3141 /* pCode2str - convert a pCode instruction to string */
3142 /*-----------------------------------------------------------------*/
3143 char *pCode2str(char *str, size_t size, pCode *pc)
3151 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3153 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3155 if(PCI(pc)->isBitInst) {
3156 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3157 char *name = PCI(pc)->pcop->name;
3159 name = PCOR(PCI(pc)->pcop)->r->name;
3160 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3161 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3163 SAFE_snprintf(&s,&size,"%s,%d", name,
3164 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3165 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3166 SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3168 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3169 //PCI(pc)->pcop->t.bit );
3171 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3172 if( PCI(pc)->num_ops == 2)
3173 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3175 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3177 SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3178 if( PCI(pc)->num_ops == 2)
3179 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3186 /* assuming that comment ends with a \n */
3187 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3191 /* assuming that inline code ends with a \n */
3192 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3196 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3199 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3202 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3205 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3208 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3209 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);
3212 if(PCAD(pc)->directive) {
3213 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3214 } else if(PCAD(pc)->arg) {
3215 /* special case to handle inline labels without a tab */
3216 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3221 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3227 /*-----------------------------------------------------------------*/
3228 /* genericPrint - the contents of a pCode to a file */
3229 /*-----------------------------------------------------------------*/
3230 static void genericPrint(FILE *of, pCode *pc)
3237 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3241 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3245 // If the opcode has a label, print that first
3248 pCodeInstruction *pci = PCI(pc);
3249 pBranch *pbl = pci->label;
3250 while(pbl && pbl->pc) {
3251 if(pbl->pc->type == PC_LABEL)
3252 pCodePrintLabel(of, pbl->pc);
3257 genericPrint(of,PCODE(pci->cline));
3260 pCode2str(str, 256, pc);
3262 fprintf(of,"%s",str);
3266 pCodeOpReg *pcor = PCOR(pci->pcop);
3267 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3269 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3270 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3271 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3276 pBranch *dpb = pc->to; // debug
3278 switch ( dpb->pc->type) {
3280 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3283 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3286 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3289 fprintf(of, "\t;flow");
3303 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3304 if(PCW(pc)->pci.label)
3305 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3307 if(PCW(pc)->operand) {
3308 fprintf(of,";\toperand ");
3309 pCodeOpPrint(of,PCW(pc)->operand );
3315 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3316 if(PCFL(pc)->ancestor)
3317 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3319 fprintf(of,"; from: ");
3321 pCodeFlowLink *link;
3322 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3324 fprintf(of,"%03x ",link->pcflow->pc.seq);
3327 fprintf(of,"; to: ");
3329 pCodeFlowLink *link;
3330 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3332 fprintf(of,"%03x ",link->pcflow->pc.seq);
3340 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3341 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3346 pBranch *pbl = PCAD(pc)->pci.label;
3347 while(pbl && pbl->pc) {
3348 if(pbl->pc->type == PC_LABEL)
3349 pCodePrintLabel(of, pbl->pc);
3353 if(PCAD(pc)->directive) {
3354 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3357 /* special case to handle inline labels without tab */
3358 fprintf(of, "%s\n", PCAD(pc)->arg);
3364 fprintf(of,"unknown pCode type %d\n",pc->type);
3368 /*-----------------------------------------------------------------*/
3369 /* pCodePrintFunction - prints function begin/end */
3370 /*-----------------------------------------------------------------*/
3372 static void pCodePrintFunction(FILE *of, pCode *pc)
3378 if( ((pCodeFunction *)pc)->modname)
3379 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3381 if(PCF(pc)->fname) {
3382 pBranch *exits = PCF(pc)->to;
3384 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3387 exits = exits->next;
3390 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3393 if((PCF(pc)->from &&
3394 PCF(pc)->from->pc->type == PC_FUNCTION &&
3395 PCF(PCF(pc)->from->pc)->fname) )
3396 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3398 fprintf(of,"; exit point [can't find entry point]\n");
3401 /*-----------------------------------------------------------------*/
3402 /* pCodePrintLabel - prints label */
3403 /*-----------------------------------------------------------------*/
3405 static void pCodePrintLabel(FILE *of, pCode *pc)
3412 fprintf(of,"%s\n",PCL(pc)->label);
3413 else if (PCL(pc)->key >=0)
3414 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3416 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3420 /*-----------------------------------------------------------------*/
3421 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3422 /* remove it if it is found. */
3423 /*-----------------------------------------------------------------*/
3424 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3430 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3431 b = PCI(pcl)->label;
3433 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3437 //fprintf (stderr, "%s \n",__FUNCTION__);
3438 //pcl->print(stderr,pcl);
3439 //pc->print(stderr,pc);
3442 //fprintf (stderr, "found label\n");
3446 bprev->next = b->next; /* Not first pCode in chain */
3450 PCI(pcl)->label = b->next; /* First pCode in chain */
3453 return; /* A label can't occur more than once */
3460 /*-----------------------------------------------------------------*/
3461 /*-----------------------------------------------------------------*/
3462 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3481 /*-----------------------------------------------------------------*/
3482 /* pBranchLink - given two pcodes, this function will link them */
3483 /* together through their pBranches */
3484 /*-----------------------------------------------------------------*/
3485 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3489 // Declare a new branch object for the 'from' pCode.
3491 //_ALLOC(b,sizeof(pBranch));
3492 b = Safe_calloc(1,sizeof(pBranch));
3493 b->pc = PCODE(t); // The link to the 'to' pCode.
3496 f->to = pBranchAppend(f->to,b);
3498 // Now do the same for the 'to' pCode.
3500 //_ALLOC(b,sizeof(pBranch));
3501 b = Safe_calloc(1,sizeof(pBranch));
3505 t->from = pBranchAppend(t->from,b);
3510 /*-----------------------------------------------------------------*/
3511 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3513 /*-----------------------------------------------------------------*/
3514 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3527 /*-----------------------------------------------------------------*/
3528 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3529 /*-----------------------------------------------------------------*/
3530 static void pCodeUnlink(pCode *pc)
3535 if(!pc->prev || !pc->next) {
3536 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3540 /* first remove the pCode from the chain */
3541 pc->prev->next = pc->next;
3542 pc->next->prev = pc->prev;
3544 /* Now for the hard part... */
3546 /* Remove the branches */
3550 pc1 = pb1->pc; /* Get the pCode that branches to the
3551 * one we're unlinking */
3553 /* search for the link back to this pCode (the one we're
3555 if(pb2 = pBranchFind(pc1->to,pc)) {
3556 pb2->pc = pc->to->pc; // make the replacement
3558 /* if the pCode we're unlinking contains multiple 'to'
3559 * branches (e.g. this a skip instruction) then we need
3560 * to copy these extra branches to the chain. */
3562 pBranchAppend(pb2, pc->to->next);
3571 /*-----------------------------------------------------------------*/
3572 /*-----------------------------------------------------------------*/
3574 static void genericAnalyze(pCode *pc)
3584 // Go through the pCodes that are in pCode chain and link
3585 // them together through the pBranches. Note, the pCodes
3586 // are linked together as a contiguous stream like the
3587 // assembly source code lines. The linking here mimics this
3588 // except that comments are not linked in.
3590 pCode *npc = pc->next;
3592 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3593 pBranchLink(pc,npc);
3598 /* reached the end of the pcode chain without finding
3599 * an instruction we could link to. */
3603 fprintf(stderr,"analyze PC_FLOW\n");
3607 fprintf(stderr,";A bad pCode is being used\n");
3613 /*-----------------------------------------------------------------*/
3614 /*-----------------------------------------------------------------*/
3615 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3619 if(pc->type == PC_LABEL) {
3620 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3623 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3624 pbr = PCI(pc)->label;
3626 if(pbr->pc->type == PC_LABEL) {
3627 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3637 /*-----------------------------------------------------------------*/
3638 /*-----------------------------------------------------------------*/
3639 int checkLabel(pCode *pc)
3643 if(pc && isPCI(pc)) {
3644 pbr = PCI(pc)->label;
3646 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3656 /*-----------------------------------------------------------------*/
3657 /* findLabelinpBlock - Search the pCode for a particular label */
3658 /*-----------------------------------------------------------------*/
3659 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3666 for(pc = pb->pcHead; pc; pc = pc->next)
3667 if(compareLabel(pc,pcop_label))
3673 /*-----------------------------------------------------------------*/
3674 /* findLabel - Search the pCode for a particular label */
3675 /*-----------------------------------------------------------------*/
3676 pCode * findLabel(pCodeOpLabel *pcop_label)
3684 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3685 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3689 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3693 /*-----------------------------------------------------------------*/
3694 /* findNextpCode - given a pCode, find the next of type 'pct' */
3695 /* in the linked list */
3696 /*-----------------------------------------------------------------*/
3697 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3710 /*-----------------------------------------------------------------*/
3711 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3712 /* in the linked list */
3713 /*-----------------------------------------------------------------*/
3714 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3718 if(pc->type == pct) {
3720 static unsigned int stop;
3722 stop++; // Place break point here
3733 /*-----------------------------------------------------------------*/
3734 /* findNextInstruction - given a pCode, find the next instruction */
3735 /* in the linked list */
3736 /*-----------------------------------------------------------------*/
3737 pCode * findNextInstruction(pCode *pci)
3742 if((pc->type == PC_OPCODE)
3743 || (pc->type == PC_WILD)
3744 || (pc->type == PC_ASMDIR))
3748 fprintf(stderr,"findNextInstruction: ");
3749 printpCode(stderr, pc);
3754 //fprintf(stderr,"Couldn't find instruction\n");
3758 /*-----------------------------------------------------------------*/
3759 /* findNextInstruction - given a pCode, find the next instruction */
3760 /* in the linked list */
3761 /*-----------------------------------------------------------------*/
3762 pCode * findPrevInstruction(pCode *pci)
3768 if((pc->type == PC_OPCODE)
3769 || (pc->type == PC_WILD)
3770 || (pc->type == PC_ASMDIR))
3775 fprintf(stderr,"pic16_findPrevInstruction: ");
3776 printpCode(stderr, pc);
3781 //fprintf(stderr,"Couldn't find instruction\n");
3785 /*-----------------------------------------------------------------*/
3786 /* findFunctionEnd - given a pCode find the end of the function */
3787 /* that contains it */
3788 /*-----------------------------------------------------------------*/
3789 pCode * findFunctionEnd(pCode *pc)
3792 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3798 fprintf(stderr,"Couldn't find function end\n");
3803 /*-----------------------------------------------------------------*/
3804 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3805 /* instruction with which it is associated. */
3806 /*-----------------------------------------------------------------*/
3807 static void AnalyzeLabel(pCode *pc)
3816 static void AnalyzeGOTO(pCode *pc)
3819 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3823 static void AnalyzeSKIP(pCode *pc)
3826 pBranchLink(pc,findNextInstruction(pc->next));
3827 pBranchLink(pc,findNextInstruction(pc->next->next));
3831 static void AnalyzeRETURN(pCode *pc)
3834 // branch_link(pc,findFunctionEnd(pc->next));
3840 /*-----------------------------------------------------------------*/
3841 /*-----------------------------------------------------------------*/
3842 regs * getRegFromInstruction(pCode *pc)
3848 PCI(pc)->num_ops == 0 )
3851 switch(PCI(pc)->pcop->type) {
3858 case PO_SFR_REGISTER:
3861 return PCOR(PCI(pc)->pcop)->r;
3863 case PO_GPR_REGISTER:
3866 r = PCOR(PCI(pc)->pcop)->r;
3869 return dirregWithName(PCI(pc)->pcop->name);
3875 r = PCOI(PCI(pc)->pcop)->r;
3878 return dirregWithName(PCI(pc)->pcop->name);
3888 /*-----------------------------------------------------------------*/
3889 /*-----------------------------------------------------------------*/
3891 void AnalyzepBlock(pBlock *pb)
3898 /* Find all of the registers used in this pBlock
3899 * by looking at each instruction and examining it's
3902 for(pc = pb->pcHead; pc; pc = pc->next) {
3904 /* Is this an instruction with operands? */
3905 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3907 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3908 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3910 /* Loop through all of the registers declared so far in
3911 this block and see if we find this one there */
3913 regs *r = setFirstItem(pb->tregisters);
3916 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3917 PCOR(PCI(pc)->pcop)->r = r;
3920 r = setNextItem(pb->tregisters);
3924 /* register wasn't found */
3925 //r = Safe_calloc(1, sizeof(regs));
3926 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3927 //addSet(&pb->tregisters, r);
3928 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3929 //PCOR(PCI(pc)->pcop)->r = r;
3930 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3932 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3935 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3936 if(PCOR(PCI(pc)->pcop)->r) {
3937 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3938 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3940 if(PCI(pc)->pcop->name)
3941 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3943 fprintf(stderr,"ERROR: NULL register\n");
3952 /*-----------------------------------------------------------------*/
3954 /*-----------------------------------------------------------------*/
3955 void InsertpFlow(pCode *pc, pCode **pflow)
3958 PCFL(*pflow)->end = pc;
3960 if(!pc || !pc->next)
3963 *pflow = newpCodeFlow();
3964 pCodeInsertAfter(pc, *pflow);
3967 /*-----------------------------------------------------------------*/
3968 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3969 /* the flow blocks. */
3971 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3972 * point the instruction flow changes.
3974 /*-----------------------------------------------------------------*/
3975 void BuildFlow(pBlock *pb)
3978 pCode *last_pci=NULL;
3985 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3986 /* Insert a pCodeFlow object at the beginning of a pBlock */
3988 InsertpFlow(pb->pcHead, &pflow);
3990 //pflow = newpCodeFlow(); /* Create a new Flow object */
3991 //pflow->next = pb->pcHead; /* Make the current head the next object */
3992 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3993 //pb->pcHead = pflow; /* Make the Flow object the head */
3996 for( pc = findNextInstruction(pb->pcHead);
3998 pc=findNextInstruction(pc)) {
4001 PCI(pc)->pcflow = PCFL(pflow);
4003 //fprintf(stderr," build: ");
4004 //pc->print(stderr, pc);
4005 //pflow->print(stderr,pflow);
4007 if (checkLabel(pc)) {
4009 /* This instruction marks the beginning of a
4010 * new flow segment */
4015 /* If the previous pCode is not a flow object, then
4016 * insert a new flow object. (This check prevents
4017 * two consecutive flow objects from being insert in
4018 * the case where a skip instruction preceeds an
4019 * instruction containing a label.) */
4021 last_pci = findPrevInstruction (pc->prev);
4023 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4024 InsertpFlow(last_pci, &pflow);
4026 PCI(pc)->pcflow = PCFL(pflow);
4030 if(isPCI_SKIP(pc)) {
4032 /* The two instructions immediately following this one
4033 * mark the beginning of a new flow segment */
4035 while(pc && isPCI_SKIP(pc)) {
4037 PCI(pc)->pcflow = PCFL(pflow);
4041 InsertpFlow(pc, &pflow);
4042 pc=findNextInstruction(pc->next);
4050 PCI(pc)->pcflow = PCFL(pflow);
4052 InsertpFlow(pc, &pflow);
4054 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4056 InsertpFlow(pc, &pflow);
4065 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4067 PCFL(pflow)->end = pb->pcTail;
4070 /*-------------------------------------------------------------------*/
4071 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4072 /* the flow blocks. */
4074 * unBuildFlow removes pCodeFlow objects from a pCode chain
4076 /*-----------------------------------------------------------------*/
4077 void unBuildFlow(pBlock *pb)
4092 if(PCI(pc)->pcflow) {
4093 //free(PCI(pc)->pcflow);
4094 PCI(pc)->pcflow = NULL;
4097 } else if(isPCFL(pc) )
4106 /*-----------------------------------------------------------------*/
4107 /*-----------------------------------------------------------------*/
4108 void dumpCond(int cond)
4111 static char *pcc_str[] = {
4125 int ncond = sizeof(pcc_str) / sizeof(char *);
4128 fprintf(stderr, "0x%04X\n",cond);
4130 for(i=0,j=1; i<ncond; i++, j<<=1)
4132 fprintf(stderr, " %s\n",pcc_str[i]);
4136 /*-----------------------------------------------------------------*/
4137 /*-----------------------------------------------------------------*/
4138 void FlowStats(pCodeFlow *pcflow)
4146 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4148 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4151 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4156 fprintf(stderr, " FlowStats inCond: ");
4157 dumpCond(pcflow->inCond);
4158 fprintf(stderr, " FlowStats outCond: ");
4159 dumpCond(pcflow->outCond);
4163 /*-----------------------------------------------------------------*
4164 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4165 * if it affects the banking bits.
4167 * return: -1 == Banking bits are unaffected by this pCode.
4169 * return: > 0 == Banking bits are affected.
4171 * If the banking bits are affected, then the returned value describes
4172 * which bits are affected and how they're affected. The lower half
4173 * of the integer maps to the bits that are affected, the upper half
4174 * to whether they're set or cleared.
4176 *-----------------------------------------------------------------*/
4178 #define SET_BANK_BIT (1 << 16)
4179 #define CLR_BANK_BIT 0
4181 static int isBankInstruction(pCode *pc)
4189 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4191 // Check to see if the register banks are changing
4192 if(PCI(pc)->isModReg) {
4194 pCodeOp *pcop = PCI(pc)->pcop;
4195 switch(PCI(pc)->op) {
4198 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4199 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4200 return SET_BANK_BIT | PIC_RP0_BIT;
4203 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4204 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4205 return CLR_BANK_BIT | PIC_RP0_BIT;
4210 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4211 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4212 return CLR_BANK_BIT | PIC_RP1_BIT;
4214 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4215 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4216 return CLR_BANK_BIT | PIC_RP1_BIT;
4220 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4221 //genericPrint(stderr, pc);
4232 /*-----------------------------------------------------------------*/
4233 /*-----------------------------------------------------------------*/
4235 static void FillFlow(pCodeFlow *pcflow)
4243 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4245 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4248 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4255 isBankInstruction(pc);
4257 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4260 fprintf(stderr, " FillFlow - Bad end of flow\n");
4262 fprintf(stderr, " FillFlow - Ending flow with\n ");
4263 pc->print(stderr,pc);
4266 fprintf(stderr, " FillFlow inCond: ");
4267 dumpCond(pcflow->inCond);
4268 fprintf(stderr, " FillFlow outCond: ");
4269 dumpCond(pcflow->outCond);
4274 /*-----------------------------------------------------------------*/
4275 /*-----------------------------------------------------------------*/
4276 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4278 pCodeFlowLink *fromLink, *toLink;
4280 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4281 if (from) from->pc.print(stderr, &from->pc);
4282 else fprintf(stderr, "(null)");
4283 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4284 from && from->pcflow ? from->pcflow->pc.seq : 0,
4285 to && to->pcflow ? to->pcflow->pc.seq : 0);
4286 if (to) to->pc.print(stderr, &to->pc);
4287 else fprintf(stderr, "(null)");
4290 if(!from || !to || !to->pcflow || !from->pcflow)
4293 fromLink = newpCodeFlowLink(from->pcflow);
4294 toLink = newpCodeFlowLink(to->pcflow);
4296 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4297 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4301 /*-----------------------------------------------------------------*
4302 * void LinkFlow(pBlock *pb)
4304 * In BuildFlow, the PIC code has been partitioned into contiguous
4305 * non-branching segments. In LinkFlow, we determine the execution
4306 * order of these segments. For example, if one of the segments ends
4307 * with a skip, then we know that there are two possible flow segments
4308 * to which control may be passed.
4309 *-----------------------------------------------------------------*/
4310 void LinkFlow(pBlock *pb)
4316 //fprintf(stderr,"linkflow \n");
4320 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4322 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4325 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4327 //fprintf(stderr," link: ");
4328 //pcflow->print(stderr,pcflow);
4330 //FillFlow(PCFL(pcflow));
4332 /* find last instruction in flow */
4333 pc = findPrevInstruction (PCFL(pcflow)->end);
4335 fprintf(stderr, "%s: flow without end (%u)?\n",
4336 __FUNCTION__, pcflow->seq );
4340 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4341 //pc->print(stderr, pc);
4342 if(isPCI_SKIP(pc)) {
4343 //fprintf(stderr, "ends with skip\n");
4344 //pc->print(stderr,pc);
4345 pct=findNextInstruction(pc->next);
4346 LinkFlow_pCode(PCI(pc),PCI(pct));
4347 pct=findNextInstruction(pct->next);
4348 LinkFlow_pCode(PCI(pc),PCI(pct));
4352 if(isPCI_BRANCH(pc)) {
4353 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4355 //fprintf(stderr, "ends with branch\n ");
4356 //pc->print(stderr,pc);
4358 if(!(pcol && isPCOLAB(pcol))) {
4359 if((PCI(pc)->op != POC_RETLW)
4360 && (PCI(pc)->op != POC_RETURN)
4361 && (PCI(pc)->op != POC_CALL)
4362 && (PCI(pc)->op != POC_RETFIE) )
4364 pc->print(stderr,pc);
4365 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4369 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4370 LinkFlow_pCode(PCI(pc),PCI(pct));
4372 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4373 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4374 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4376 /* link CALLs to next instruction */
4377 if (PCI(pc)->op != POC_CALL) continue;
4381 //fprintf(stderr, "ends with non-branching instruction:\n");
4382 //pc->print(stderr,pc);
4384 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4390 //fprintf(stderr, "ends with unknown\n");
4391 //pc->print(stderr,pc);
4395 fprintf(stderr, "ends with nothing: ERROR\n");
4399 /*-----------------------------------------------------------------*/
4400 /*-----------------------------------------------------------------*/
4402 /*-----------------------------------------------------------------*/
4403 /*-----------------------------------------------------------------*/
4404 int isPCinFlow(pCode *pc, pCode *pcflow)
4410 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4413 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4419 /*-----------------------------------------------------------------*/
4420 /*-----------------------------------------------------------------*/
4422 static void BanksUsedFlow2(pCode *pcflow)
4431 if(!isPCFL(pcflow)) {
4432 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4436 pc = findNextInstruction(pcflow->next);
4438 PCFL(pcflow)->lastBank = -1;
4440 while(isPCinFlow(pc,pcflow)) {
4442 int bank_selected = isBankInstruction(pc);
4444 //if(PCI(pc)->pcflow)
4445 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4447 if(bank_selected > 0) {
4448 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4450 // This instruction is modifying banking bits before accessing registers
4452 PCFL(pcflow)->firstBank = -1;
4454 if(PCFL(pcflow)->lastBank == -1)
4455 PCFL(pcflow)->lastBank = 0;
4457 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4458 if(bank_selected & SET_BANK_BIT)
4459 PCFL(pcflow)->lastBank |= bank;
4463 reg = getRegFromInstruction(pc);
4465 if(reg && !isREGinBank(reg, bank)) {
4466 int allbanks = REGallBanks(reg);
4468 PCFL(pcflow)->firstBank = allbanks;
4470 PCFL(pcflow)->lastBank = allbanks;
4477 pc = findNextInstruction(pc->next);
4480 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4481 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4484 /*-----------------------------------------------------------------*/
4485 /*-----------------------------------------------------------------*/
4487 static void BanksUsedFlow(pBlock *pb)
4492 //pb->pcHead->print(stderr, pb->pcHead);
4494 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4495 //pcflow->print(stderr,pcflow);
4497 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4499 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4501 BanksUsedFlow2(pcflow);
4507 void pCodeReplace (pCode *old, pCode *new)
4509 pCodeInsertAfter (old, new);
4511 /* special handling for pCodeInstructions */
4512 if (isPCI(new) && isPCI(old))
4514 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4515 PCI(new)->from = PCI(old)->from;
4516 PCI(new)->to = PCI(old)->to;
4517 PCI(new)->label = PCI(old)->label;
4518 PCI(new)->pcflow = PCI(old)->pcflow;
4519 PCI(new)->cline = PCI(old)->cline;
4522 old->destruct (old);
4525 /*-----------------------------------------------------------------*/
4526 /*-----------------------------------------------------------------*/
4527 void addpCodeComment(pCode *pc, const char *fmt, ...)
4534 if (options.verbose || debug_verbose) {
4537 vsprintf(&buffer[2], fmt, ap);
4539 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4540 pCodeInsertAfter(pc, newpc);
4545 void pBlockMergeLabels(pBlock *pb);
4546 /*-----------------------------------------------------------------*/
4547 /* Inserts a new pCodeInstruction before an existing one */
4548 /*-----------------------------------------------------------------*/
4549 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4553 pcprev = findPrevInstruction(pci->pc.prev);
4555 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4557 /* Move the label, if there is one */
4560 new_pci->label = pci->label;
4564 /* Move the C code comment, if there is one */
4567 new_pci->cline = pci->cline;
4571 /* The new instruction has the same pcflow block */
4572 new_pci->pcflow = pci->pcflow;
4574 /* Arrrrg: is pci's previous instruction is a skip, we need to
4575 * change that into a jump (over pci and the new instruction) ... */
4576 if (pcprev && isPCI_SKIP(pcprev))
4578 symbol *lbl = newiTempLabel (NULL);
4579 pCode *label = newpCodeLabel (NULL, lbl->key);
4580 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4582 pCodeInsertAfter (pcprev, jump);
4584 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4585 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4586 switch (PCI(pcprev)->op) {
4591 // These are turned into non-skipping instructions, so
4592 // insert 'BTFSC STATUS, Z' after pcprev
4593 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4596 // no special actions required
4599 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4601 pCodeInsertAfter((pCode*)pci, label);
4602 pBlockMergeLabels(pci->pc.pb);
4606 /*-----------------------------------------------------------------*/
4607 /*-----------------------------------------------------------------*/
4608 static void insertBankSel(pCodeInstruction *pci, const char *name)
4614 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4615 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4617 pcop = popCopyReg(PCOR(pci->pcop));
4618 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4619 if (pcop->name == 0)
4620 pcop->name = strdup(name);
4621 new_pc = newpCode(POC_BANKSEL, pcop);
4623 insertPCodeInstruction(pci, PCI(new_pc));
4627 * isValidIdChar - check if c may be present in an identifier
4629 static int isValidIdChar (char c)
4631 if (c >= 'a' && c <= 'z') return 1;
4632 if (c >= 'A' && c <= 'Z') return 1;
4633 if (c >= '0' && c <= '9') return 1;
4634 if (c == '_') return 1;
4639 * bankcompare - check if two operand string refer to the same register
4640 * This functions handles NAME and (NAME + x) in both operands.
4641 * Returns 1 on same register, 0 on different (or unknown) registers.
4643 static int bankCompare(const char *op1, const char *op2)
4647 if (!op1 && !op2) return 0; // both unknown, might be different though!
4648 if (!op1 || !op2) return 0;
4650 // find start of operand name
4651 while (op1[0] == '(' || op1[0] == ' ') op1++;
4652 while (op2[0] == '(' || op2[0] == ' ') op2++;
4654 // compare till first non-identifier character
4655 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4656 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4658 // play safe---assume different operands
4662 /*-----------------------------------------------------------------*/
4663 /*-----------------------------------------------------------------*/
4664 extern int pic14_operandsAllocatedInSameBank(const char *str1, const char *str2);
4665 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4667 if (!cur_bank) return 0;
4669 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4670 return 1; // if we have address info, we use it for banksel optimization
4672 // regard '(regname + X)' and '(regname + Y)' as equal
4673 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4674 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4676 // check allocation policy from glue.c
4677 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4678 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4680 // seems to be a different operand--might be a different bank
4681 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4685 /*-----------------------------------------------------------------*/
4686 /*-----------------------------------------------------------------*/
4687 void FixRegisterBanking(pBlock *pb)
4690 pCodeInstruction *pci;
4692 regs *previous_reg; // contains the previous variable access info
4693 const char *cur_bank, *new_bank;
4694 unsigned cur_mask, new_mask, max_mask;
4699 max_mask = pic14_getPIC()->bankMask;
4700 cur_mask = max_mask;
4702 previous_reg = NULL;
4704 allRAMmshared = pic14_allRAMShared();
4706 for (pc = pb->pcHead; pc; pc = pc->next)
4708 // this one has a label---might check bank at all jumps here...
4709 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4710 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4711 previous_reg = NULL;
4712 cur_bank = NULL; // start new flow
4713 cur_mask = max_mask;
4716 // this one is/might be a label or BANKSEL---assume nothing
4717 if (isPCL(pc) || isPCASMDIR(pc)) {
4718 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4719 previous_reg = NULL;
4721 cur_mask = max_mask;
4724 // this one modifies STATUS
4725 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4729 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4730 // might need a BANKSEL
4731 reg = getRegFromInstruction(pc);
4734 new_bank = reg->name;
4735 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4736 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4737 new_mask = reg->alias;
4738 } else if (pci->pcop && pci->pcop->name) {
4739 new_bank = pci->pcop->name;
4740 new_mask = 0; // unknown, assume worst case
4742 assert(!"Could not get register from instruction.");
4743 new_bank = "UNKNOWN";
4744 new_mask = 0; // unknown, assume worst case
4748 // XXX: add switch to disable these
4750 // reg present in all banks possibly selected?
4751 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4752 // no BANKSEL required
4753 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4757 // only one bank of memory and no SFR accessed?
4758 // XXX: We can do better with fixed registers.
4759 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4760 // no BANKSEL required
4761 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4765 // restrict cur_mask to cover only the banks this register
4766 // is in (as well as the previous registers)
4767 cur_mask &= new_mask;
4769 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4770 // no BANKSEL required
4771 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4776 cur_mask = new_mask;
4777 cur_bank = new_bank;
4779 insertBankSel(pci, cur_bank);
4785 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4787 int OptimizepBlock(pBlock *pb)
4792 if(!pb || options.nopeep)
4795 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4797 for(pc = pb->pcHead; pc; pc = pc->next)
4798 matches += pCodePeepMatchRule(pc);
4801 pc = findNextInstruction(pb->pcHead);
4809 if(pCodePeepMatchRule(pc)) {
4814 pc = findNextInstruction(pcprev->next);
4816 pc = findNextInstruction(pb->pcHead);
4818 pc = findNextInstruction(pc->next);
4822 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4827 /*-----------------------------------------------------------------*/
4828 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4829 /*-----------------------------------------------------------------*/
4830 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4834 for(pc = pcs; pc; pc = pc->next) {
4836 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4838 (PCI(pc)->pcop->type == PO_LABEL) &&
4839 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4846 /*-----------------------------------------------------------------*/
4847 /*-----------------------------------------------------------------*/
4848 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4855 (PCI(pc)->pcop->type == PO_LABEL)) {
4857 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4859 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4861 free(pcol->pcop.name);
4863 /* If the key is negative, then we (probably) have a label to
4864 * a function and the name is already defined */
4867 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4871 //sprintf(buffer,"_%05d_DS_",pcl->key);
4873 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4875 pcol->pcop.name = Safe_strdup(s);
4876 pcol->key = pcl->key;
4877 //pc->print(stderr,pc);
4884 /*-----------------------------------------------------------------*/
4885 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4886 /* pCode chain if they're not used. */
4887 /*-----------------------------------------------------------------*/
4888 void pBlockRemoveUnusedLabels(pBlock *pb)
4890 pCode *pc; pCodeLabel *pcl;
4892 if(!pb || !pb->pcHead)
4895 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4897 pBranch *pbr = PCI(pc)->label;
4898 if(pbr && pbr->next) {
4899 pCode *pcd = pb->pcHead;
4901 //fprintf(stderr, "multiple labels\n");
4902 //pc->print(stderr,pc);
4907 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4908 //fprintf(stderr,"Used by:\n");
4909 //pcd->print(stderr,pcd);
4911 exchangeLabels(PCL(pbr->pc),pcd);
4920 for(pc = pb->pcHead; pc; pc = pc->next) {
4922 if(isPCL(pc)) // Label pcode
4924 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4925 pcl = PCL(PCI(pc)->label->pc);
4928 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4930 /* This pCode is a label, so search the pBlock to see if anyone
4933 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4934 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4935 /* Couldn't find an instruction that refers to this label
4936 * So, unlink the pCode label from it's pCode chain
4937 * and destroy the label */
4938 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4940 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4941 if(pc->type == PC_LABEL) {
4943 pCodeLabelDestruct(pc);
4945 unlinkpCodeFromBranch(pc, PCODE(pcl));
4946 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4957 /*-----------------------------------------------------------------*/
4958 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4959 /* chain and put them into pBranches that are */
4960 /* associated with the appropriate pCode */
4962 /*-----------------------------------------------------------------*/
4963 void pBlockMergeLabels(pBlock *pb)
4966 pCode *pc, *pcnext=NULL;
4971 /* First, Try to remove any unused labels */
4972 //pBlockRemoveUnusedLabels(pb);
4974 /* Now loop through the pBlock and merge the labels with the opcodes */
4977 // for(pc = pb->pcHead; pc; pc = pc->next) {
4980 pCode *pcn = pc->next;
4982 if(pc->type == PC_LABEL) {
4984 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4985 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4986 if((pcnext = findNextInstruction(pc) )) {
4988 // Unlink the pCode label from it's pCode chain
4991 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4992 // And link it into the instruction's pBranch labels. (Note, since
4993 // it's possible to have multiple labels associated with one instruction
4994 // we must provide a means to accomodate the additional labels. Thus
4995 // the labels are placed into the singly-linked list "label" as
4996 // opposed to being a single member of the pCodeInstruction.)
4998 //_ALLOC(pbr,sizeof(pBranch));
4999 pbr = Safe_calloc(1,sizeof(pBranch));
5003 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5006 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5008 } else if(pc->type == PC_CSOURCE) {
5010 /* merge the source line symbolic info into the next instruction */
5011 if((pcnext = findNextInstruction(pc) )) {
5013 // Unlink the pCode label from it's pCode chain
5015 PCI(pcnext)->cline = PCCS(pc);
5016 //fprintf(stderr, "merging CSRC\n");
5017 //genericPrint(stderr,pcnext);
5023 pBlockRemoveUnusedLabels(pb);
5027 /*-----------------------------------------------------------------*/
5028 /*-----------------------------------------------------------------*/
5029 int OptimizepCode(char dbName)
5031 #define MAX_PASSES 4
5040 DFPRINTF((stderr," Optimizing pCode\n"));
5044 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5045 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5046 matches += OptimizepBlock(pb);
5049 while(matches && ++passes < MAX_PASSES);
5054 /*-----------------------------------------------------------------*/
5055 /* popCopyGPR2Bit - copy a pcode operator */
5056 /*-----------------------------------------------------------------*/
5058 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5062 pcop = newpCodeOpBit(pc->name, bitval, 0);
5064 if( !( (pcop->type == PO_LABEL) ||
5065 (pcop->type == PO_LITERAL) ||
5066 (pcop->type == PO_STR) ))
5067 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5072 /*-----------------------------------------------------------------*/
5073 /*-----------------------------------------------------------------*/
5074 void pBlockDestruct(pBlock *pb)
5085 /*-----------------------------------------------------------------*/
5086 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5087 /* name dbName and combine them */
5088 /* into one block */
5089 /*-----------------------------------------------------------------*/
5090 void mergepBlocks(char dbName)
5093 pBlock *pb, *pbmerged = NULL,*pbn;
5095 pb = the_pFile->pbHead;
5097 //fprintf(stderr," merging blocks named %c\n",dbName);
5101 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5102 if( getpBlock_dbName(pb) == dbName) {
5104 //fprintf(stderr," merged block %c\n",dbName);
5109 addpCode2pBlock(pbmerged, pb->pcHead);
5110 /* addpCode2pBlock doesn't handle the tail: */
5111 pbmerged->pcTail = pb->pcTail;
5113 pb->prev->next = pbn;
5115 pbn->prev = pb->prev;
5120 //printpBlock(stderr, pbmerged);
5127 /*-----------------------------------------------------------------*/
5128 /* AnalyzeFlow - Examine the flow of the code and optimize */
5130 /* level 0 == minimal optimization */
5131 /* optimize registers that are used only by two instructions */
5132 /* level 1 == maximal optimization */
5133 /* optimize by looking at pairs of instructions that use the */
5135 /*-----------------------------------------------------------------*/
5137 void AnalyzeFlow(int level)
5139 static int times_called=0;
5147 /* if this is not the first time this function has been called,
5148 then clean up old flow information */
5149 if(times_called++) {
5150 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5153 RegsUnMapLiveRanges();
5159 /* Phase 2 - Flow Analysis - Register Banking
5161 * In this phase, the individual flow blocks are examined
5162 * and register banking is fixed.
5165 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5166 //FixRegisterBanking(pb);
5168 /* Phase 2 - Flow Analysis
5170 * In this phase, the pCode is partition into pCodeFlow
5171 * blocks. The flow blocks mark the points where a continuous
5172 * stream of instructions changes flow (e.g. because of
5173 * a call or goto or whatever).
5176 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5180 /* Phase 2 - Flow Analysis - linking flow blocks
5182 * In this phase, the individual flow blocks are examined
5183 * to determine their order of excution.
5186 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5189 /* Phase 3 - Flow Analysis - Flow Tree
5191 * In this phase, the individual flow blocks are examined
5192 * to determine their order of excution.
5195 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5199 /* Phase x - Flow Analysis - Used Banks
5201 * In this phase, the individual flow blocks are examined
5202 * to determine the Register Banks they use
5205 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5209 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5210 pCodeRegMapLiveRanges(pb);
5212 RemoveUnusedRegisters();
5214 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5215 pCodeRegOptimizeRegUsage(level);
5220 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5225 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5227 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5228 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5229 pcflow = pcflow->next) {
5231 FillFlow(PCFL(pcflow));
5236 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5238 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5239 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5240 pcflow = pcflow->next) {
5242 FlowStats(PCFL(pcflow));
5248 /*-----------------------------------------------------------------*/
5249 /* AnalyzeBanking - Called after the memory addresses have been */
5250 /* assigned to the registers. */
5252 /*-----------------------------------------------------------------*/
5254 void AnalyzeBanking(void)
5258 if(!picIsInitialized()) {
5259 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5263 if (!the_pFile) return;
5265 /* Phase x - Flow Analysis - Used Banks
5267 * In this phase, the individual flow blocks are examined
5268 * to determine the Register Banks they use
5274 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5275 // BanksUsedFlow(pb);
5276 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5277 FixRegisterBanking(pb);
5284 /*-----------------------------------------------------------------*/
5285 /*-----------------------------------------------------------------*/
5286 DEFSETFUNC (resetrIdx)
5288 regs *r = (regs *)item;
5296 /*-----------------------------------------------------------------*/
5297 /* InitRegReuse - Initialises variables for code analyzer */
5298 /*-----------------------------------------------------------------*/
5299 void InitReuseReg(void)
5301 /* Find end of statically allocated variables for start idx */
5302 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5303 /* XXX: Avoid clashes with fixed registers, start late. */
5304 unsigned maxIdx = 0x1000;
5306 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5307 if (r->type != REG_SFR) {
5308 maxIdx += r->size; /* Increment for all statically allocated variables */
5312 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5315 /*-----------------------------------------------------------------*/
5316 /*-----------------------------------------------------------------*/
5317 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
5321 /* check recursion */
5322 pc = setFirstItem(pb->function_entries);
5327 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5333 DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
5335 if (pb->tregisters) {
5337 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5338 if (r->type == REG_GPR) {
5340 if (r->rIdx < (int)idx) {
5343 // make sure, idx is not yet used in this routine...
5345 regset = pb->tregisters;
5346 // do not touch s->curr ==> outer loop!
5347 while (regset && ((regs *)regset->item)->rIdx != idx) {
5348 regset = regset->next;
5353 if (peakIdx < idx) peakIdx = idx;
5354 sprintf(s,"r0x%02X", r->rIdx);
5355 DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
5357 r->name = Safe_strdup(s);
5363 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5365 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5366 char *dest = get_op_from_instruction(PCI(pc));
5368 pCode *pcn = findFunction(dest);
5370 /* This index increment from subroutines is not required, as all subroutines
5371 * may share registers NOT used by this one (< idx).
5372 * BUT if called functions A and B share a register, which gets assigned
5373 * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
5375 * As an alternative to this "solution" we could check above whether an
5376 * to-be-assigned rIdx is already present in the register set of the
5377 * current function. This would increase the reused registers and make this
5378 * `idx =' irrelevant.
5379 * UPDATE: Implemented above; not fast, but works.
5380 * (Problem shown with regression test src/regression/sub2.c)
5382 /*idx = */register_reassign(pcn->pb,idx,level+1);
5390 /*------------------------------------------------------------------*/
5391 /* ReuseReg were call tree permits */
5393 /* Re-allocate the GPR for optimum reuse for a given pblock */
5394 /* eg if a function m() calls function f1() and f2(), where f1 */
5395 /* allocates a local variable vf1 and f2 allocates a local */
5396 /* variable vf2. Then providing f1 and f2 do not call each other */
5397 /* they may share the same general purpose registers for vf1 and */
5399 /* This is done by first setting the the regs rIdx to start after */
5400 /* all the global variables, then walking through the call tree */
5401 /* renaming the registers to match their new idx and incrementng */
5402 /* it as it goes. If a function has already been called it will */
5403 /* only rename the registers if it has already used up those */
5404 /* registers ie rIdx of the function's registers is lower than the */
5405 /* current rIdx. That way the register will not be reused while */
5406 /* still being used by an eariler function call. */
5408 /* Note for this to work the functions need to be declared static. */
5410 /*------------------------------------------------------------------*/
5414 if (!the_pFile) return;
5416 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5417 /* Non static functions can be called from other modules so their registers must reassign */
5418 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5419 register_reassign(pb,peakIdx,0);
5423 /*-----------------------------------------------------------------*/
5424 /* buildCallTree - look at the flow and extract all of the calls */
5426 /*-----------------------------------------------------------------*/
5428 void buildCallTree(void )
5437 /* Now build the call tree.
5438 First we examine all of the pCodes for functions.
5439 Keep in mind that the function boundaries coincide
5440 with pBlock boundaries.
5442 The algorithm goes something like this:
5443 We have two nested loops. The outer loop iterates
5444 through all of the pBlocks/functions. The inner
5445 loop iterates through all of the pCodes for
5446 a given pBlock. When we begin iterating through
5447 a pBlock, the variable pc_fstart, pCode of the start
5448 of a function, is cleared. We then search for pCodes
5449 of type PC_FUNCTION. When one is encountered, we
5450 initialize pc_fstart to this and at the same time
5451 associate a new pBranch object that signifies a
5452 branch entry. If a return is found, then this signifies
5453 a function exit point. We'll link the pCodes of these
5454 returns to the matching pc_fstart.
5456 When we're done, a doubly linked list of pBranches
5457 will exist. The head of this list is stored in
5458 `the_pFile', which is the meta structure for all
5459 of the pCode. Look at the printCallTree function
5460 on how the pBranches are linked together.
5463 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5464 pCode *pc_fstart=NULL;
5465 for(pc = pb->pcHead; pc; pc = pc->next) {
5467 pCodeFunction *pcf = PCF(pc);
5470 if(STRCASECMP(pcf->fname, "_main") == 0) {
5471 //fprintf(stderr," found main \n");
5472 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5476 pbr = Safe_calloc(1,sizeof(pBranch));
5477 pbr->pc = pc_fstart = pc;
5480 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5482 // Here's a better way of doing the same:
5483 addSet(&pb->function_entries, pc);
5486 // Found an exit point in a function, e.g. return
5487 // (Note, there may be more than one return per function)
5489 pBranchLink(PCF(pc_fstart), pcf);
5491 addSet(&pb->function_exits, pc);
5493 } else if(isCALL(pc)) {
5494 addSet(&pb->function_calls,pc);
5500 /*-----------------------------------------------------------------*/
5501 /* AnalyzepCode - parse the pCode that has been generated and form */
5502 /* all of the logical connections. */
5504 /* Essentially what's done here is that the pCode flow is */
5506 /*-----------------------------------------------------------------*/
5508 void AnalyzepCode(char dbName)
5519 /* Phase 1 - Register allocation and peep hole optimization
5521 * The first part of the analysis is to determine the registers
5522 * that are used in the pCode. Once that is done, the peep rules
5523 * are applied to the code. We continue to loop until no more
5524 * peep rule optimizations are found (or until we exceed the
5525 * MAX_PASSES threshold).
5527 * When done, the required registers will be determined.
5533 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5535 /* First, merge the labels with the instructions */
5536 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5537 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5539 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5540 pBlockMergeLabels(pb);
5543 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5547 changes = OptimizepCode(dbName);
5549 } while(changes && (i++ < MAX_PASSES));
5554 /*-----------------------------------------------------------------*/
5555 /* ispCodeFunction - returns true if *pc is the pCode of a */
5557 /*-----------------------------------------------------------------*/
5558 bool ispCodeFunction(pCode *pc)
5561 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5567 /*-----------------------------------------------------------------*/
5568 /* findFunction - Search for a function by name (given the name) */
5569 /* in the set of all functions that are in a pBlock */
5570 /* (note - I expect this to change because I'm planning to limit */
5571 /* pBlock's to just one function declaration */
5572 /*-----------------------------------------------------------------*/
5573 pCode *findFunction(char *fname)
5580 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5582 pc = setFirstItem(pb->function_entries);
5585 if((pc->type == PC_FUNCTION) &&
5587 (strcmp(fname, PCF(pc)->fname)==0))
5590 pc = setNextItem(pb->function_entries);
5598 void MarkUsedRegisters(set *regset)
5603 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5604 r2 = pic14_regWithIdx(r1->rIdx);
5612 void pBlockStats(FILE *of, pBlock *pb)
5618 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5620 // for now just print the first element of each set
5621 pc = setFirstItem(pb->function_entries);
5623 fprintf(of,";entry: ");
5626 pc = setFirstItem(pb->function_exits);
5628 fprintf(of,";has an exit\n");
5632 pc = setFirstItem(pb->function_calls);
5634 fprintf(of,";functions called:\n");
5637 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5638 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5640 pc = setNextItem(pb->function_calls);
5644 r = setFirstItem(pb->tregisters);
5646 int n = elementsInSet(pb->tregisters);
5648 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5651 fprintf(of,"; %s\n",r->name);
5652 r = setNextItem(pb->tregisters);
5657 /*-----------------------------------------------------------------*/
5658 /*-----------------------------------------------------------------*/
5660 static void sequencepCode(void)
5666 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5668 pb->seq = GpCodeSequenceNumber+1;
5670 for( pc = pb->pcHead; pc; pc = pc->next)
5671 pc->seq = ++GpCodeSequenceNumber;
5677 /*-----------------------------------------------------------------*/
5678 /*-----------------------------------------------------------------*/
5680 set *register_usage(pBlock *pb)
5683 set *registers=NULL;
5684 set *registersInCallPath = NULL;
5686 / * check recursion * /
5688 pc = setFirstItem(pb->function_entries);
5695 if(pc->type != PC_FUNCTION)
5696 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5698 pc = setFirstItem(pb->function_calls);
5699 for( ; pc; pc = setNextItem(pb->function_calls)) {
5701 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5702 char *dest = get_op_from_instruction(PCI(pc));
5704 pcn = findFunction(dest);
5706 registersInCallPath = register_usage(pcn->pb);
5708 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5713 pBlockStats(stderr,pb); // debug
5716 // Mark the registers in this block as used.
5718 MarkUsedRegisters(pb->tregisters);
5719 if(registersInCallPath) {
5720 / * registers were used in the functions this pBlock has called * /
5721 / * so now, we need to see if these collide with the ones we are * /
5724 regs *r1,*r2, *newreg;
5726 DFPRINTF((stderr,"comparing registers\n"));
5728 r1 = setFirstItem(registersInCallPath);
5730 if (r1->type != REG_STK) {
5731 r2 = setFirstItem(pb->tregisters);
5733 while(r2 && (r2->type != REG_STK)) {
5735 if(r2->rIdx == r1->rIdx) {
5736 newreg = pic14_findFreeReg(REG_GPR);
5740 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5744 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5745 r1->rIdx, newreg->rIdx));
5746 r2->rIdx = newreg->rIdx;
5748 r2->name = Safe_strdup(newreg->name);
5752 newreg->wasUsed = 1;
5754 r2 = setNextItem(pb->tregisters);
5758 r1 = setNextItem(registersInCallPath);
5761 / * Collisions have been resolved. Now free the registers in the call path * /
5762 r1 = setFirstItem(registersInCallPath);
5764 newreg = pic14_regWithIdx(r1->rIdx);
5765 if (newreg) newreg->isFree = 1;
5766 r1 = setNextItem(registersInCallPath);
5770 // MarkUsedRegisters(pb->registers);
5772 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5775 DFPRINTF((stderr,"returning regs\n"));
5777 DFPRINTF((stderr,"not returning regs\n"));
5779 DFPRINTF((stderr,"pBlock after register optim.\n"));
5780 pBlockStats(stderr,pb); // debug
5787 /*-----------------------------------------------------------------*/
5788 /* printCallTree - writes the call tree to a file */
5790 /*-----------------------------------------------------------------*/
5791 void pct2(FILE *of,pBlock *pb,int indent)
5795 // set *registersInCallPath = NULL;
5801 return; //recursion ?
5803 pc = setFirstItem(pb->function_entries);
5810 for(i=0;i<indent;i++) // Indentation
5813 if(pc->type == PC_FUNCTION)
5814 fprintf(of,"%s\n",PCF(pc)->fname);
5819 pc = setFirstItem(pb->function_calls);
5820 for( ; pc; pc = setNextItem(pb->function_calls)) {
5822 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5823 char *dest = get_op_from_instruction(PCI(pc));
5825 pcn = findFunction(dest);
5827 pct2(of,pcn->pb,indent+1);
5829 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5837 /*-----------------------------------------------------------------*/
5838 /* printCallTree - writes the call tree to a file */
5840 /*-----------------------------------------------------------------*/
5842 void printCallTree(FILE *of)
5854 fprintf(of, "\npBlock statistics\n");
5855 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5860 fprintf(of,"Call Tree\n");
5861 pbr = the_pFile->functions;
5865 if(!ispCodeFunction(pc))
5866 fprintf(of,"bug in call tree");
5869 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5871 while(pc->next && !ispCodeFunction(pc->next)) {
5873 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5874 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5882 fprintf(of,"\n**************\n\na better call tree\n");
5883 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5888 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5889 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5895 /*-----------------------------------------------------------------*/
5897 /*-----------------------------------------------------------------*/
5899 void InlineFunction(pBlock *pb)
5907 pc = setFirstItem(pb->function_calls);
5909 for( ; pc; pc = setNextItem(pb->function_calls)) {
5912 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5913 pCode *pcp = pc->prev;
5919 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 */
5921 InlineFunction(pcn->pb);
5924 At this point, *pc points to a CALL mnemonic, and
5925 *pcn points to the function that is being called.
5927 To in-line this call, we need to remove the CALL
5928 and RETURN(s), and link the function pCode in with
5935 /* Check if previous instruction was a bit skip */
5936 if (isPCI_BITSKIP(pcp)) {
5938 /* Invert skip instruction and add a goto */
5939 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5941 if(isPCL(pc_call->next)) { // Label pcode
5942 pcl = PCL(pc_call->next);
5943 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5944 pcl = PCL(PCI(pc_call->next)->label->pc);
5946 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5947 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5949 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5952 /* remove callee pBlock from the pBlock linked list */
5953 removepBlock(pcn->pb);
5961 /* Remove the Function pCode */
5962 pct = findNextInstruction(pcn->next);
5964 /* Link the function with the callee */
5965 if (pcp) pcp->next = pcn->next;
5966 pcn->next->prev = pcp;
5968 /* Convert the function name into a label */
5970 pbr = Safe_calloc(1,sizeof(pBranch));
5971 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5973 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5974 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5976 /* turn all of the return's except the last into goto's */
5977 /* check case for 2 instruction pBlocks */
5978 pce = findNextInstruction(pcn->next);
5980 pCode *pce_next = findNextInstruction(pce->next);
5982 if(pce_next == NULL) {
5983 /* found the last return */
5984 pCode *pc_call_next = findNextInstruction(pc_call->next);
5986 //fprintf(stderr,"found last return\n");
5987 //pce->print(stderr,pce);
5988 pce->prev->next = pc_call->next;
5989 pc_call->next->prev = pce->prev;
5990 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5999 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6005 /*-----------------------------------------------------------------*/
6007 /*-----------------------------------------------------------------*/
6009 void InlinepCode(void)
6018 if(!functionInlining)
6021 /* Loop through all of the function definitions and count the
6022 * number of times each one is called */
6023 //fprintf(stderr,"inlining %d\n",__LINE__);
6025 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6027 pc = setFirstItem(pb->function_calls);
6029 for( ; pc; pc = setNextItem(pb->function_calls)) {
6032 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6033 if(pcn && isPCF(pcn)) {
6034 PCF(pcn)->ncalled++;
6037 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6042 //fprintf(stderr,"inlining %d\n",__LINE__);
6044 /* Now, Loop through the function definitions again, but this
6045 * time inline those functions that have only been called once. */
6047 InlineFunction(the_pFile->pbHead);
6048 //fprintf(stderr,"inlining %d\n",__LINE__);
6050 for(pb = the_pFile->pbHead; pb; pb = pb->next)